OstreeBootloader is temporarily public API.
src/libostree/ostree-types.h \
src/libostree/ostree-repo-file.h \
src/libostree/ostree-diff.h \
+ src/libostree/ostree-sysroot.h \
+ src/libostree/ostree-bootloader.h \
+ src/libostree/ostree-deployment.h \
+ src/libostree/ostree-bootconfig-parser.h \
$(NULL)
src/libostree/ostree-repo-file.c \
src/libostree/ostree-repo-file-enumerator.c \
src/libostree/ostree-repo-file-enumerator.h \
+ src/libostree/ostree-sysroot-private.h \
src/libostree/ostree-sysroot.c \
- src/libostree/ostree-sysroot.h \
- src/libostree/ostree-bootconfig-parser.h \
+ src/libostree/ostree-sysroot-cleanup.c \
src/libostree/ostree-bootconfig-parser.c \
- src/libostree/ostree-deployment.h \
src/libostree/ostree-deployment.c \
+ src/libostree/ostree-bootloader.c \
+ src/libostree/ostree-bootloader-syslinux.h \
+ src/libostree/ostree-bootloader-syslinux.c \
+ src/libostree/ostree-bootloader-uboot.h \
+ src/libostree/ostree-bootloader-uboot.c \
$(NULL)
if USE_LIBARCHIVE
libostree_1_la_SOURCES += src/libostree/ostree-libarchive-input-stream.h \
src/ostree/ot-admin-builtin-status.c \
src/ostree/ot-admin-builtin-upgrade.c \
src/ostree/ot-admin-builtins.h \
- src/ostree/ot-admin-cleanup.c \
src/ostree/ot-admin-util.c \
src/ostree/ot-admin-functions.h \
src/ostree/ot-admin-functions.c \
src/ostree/ot-admin-deploy.h \
src/ostree/ot-admin-deploy.c \
- src/ostree/ot-bootloader.h \
- src/ostree/ot-bootloader.c \
- src/ostree/ot-bootloader-syslinux.h \
- src/ostree/ot-bootloader-syslinux.c \
- src/ostree/ot-bootloader-uboot.h \
- src/ostree/ot-bootloader-uboot.c \
src/ostree/ot-ordered-hash.h \
src/ostree/ot-ordered-hash.c \
$(NULL)
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2013 Colin Walters <walters@verbum.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "ostree-sysroot-private.h"
+#include "ostree-bootloader-syslinux.h"
+#include "otutil.h"
+#include "libgsystem.h"
+
+#include <string.h>
+
+struct _OstreeBootloaderSyslinux
+{
+ GObject parent_instance;
+
+ OstreeSysroot *sysroot;
+ GFile *config_path;
+};
+
+typedef GObjectClass OstreeBootloaderSyslinuxClass;
+
+static void ostree_bootloader_syslinux_bootloader_iface_init (OstreeBootloaderInterface *iface);
+G_DEFINE_TYPE_WITH_CODE (OstreeBootloaderSyslinux, ostree_bootloader_syslinux, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (OSTREE_TYPE_BOOTLOADER, ostree_bootloader_syslinux_bootloader_iface_init));
+
+static gboolean
+ostree_bootloader_syslinux_query (OstreeBootloader *bootloader)
+{
+ OstreeBootloaderSyslinux *self = OSTREE_BOOTLOADER_SYSLINUX (bootloader);
+
+ return g_file_query_file_type (self->config_path, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL) == G_FILE_TYPE_SYMBOLIC_LINK;
+}
+
+static const char *
+ostree_bootloader_syslinux_get_name (OstreeBootloader *bootloader)
+{
+ return "syslinux";
+}
+
+static gboolean
+append_config_from_boostree_loader_entries (OstreeBootloaderSyslinux *self,
+ gboolean regenerate_default,
+ int bootversion,
+ GPtrArray *new_lines,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_ptrarray GPtrArray *boostree_loader_configs = NULL;
+ guint i;
+
+ if (!_ostree_sysroot_read_boot_loader_configs (self->sysroot, bootversion, &boostree_loader_configs,
+ cancellable, error))
+ goto out;
+
+ for (i = 0; i < boostree_loader_configs->len; i++)
+ {
+ OstreeBootconfigParser *config = boostree_loader_configs->pdata[i];
+ const char *val;
+
+ val = ostree_bootconfig_parser_get (config, "title");
+ if (!val)
+ val = "(Untitled)";
+
+ if (regenerate_default && i == 0)
+ {
+ g_ptr_array_add (new_lines, g_strdup_printf ("DEFAULT %s", val));
+ }
+
+ g_ptr_array_add (new_lines, g_strdup_printf ("LABEL %s", val));
+
+ val = ostree_bootconfig_parser_get (config, "linux");
+ if (!val)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "No \"linux\" key in bootloader config");
+ goto out;
+ }
+ g_ptr_array_add (new_lines, g_strdup_printf ("\tKERNEL %s", val));
+
+ val = ostree_bootconfig_parser_get (config, "initrd");
+ if (val)
+ g_ptr_array_add (new_lines, g_strdup_printf ("\tINITRD %s", val));
+
+ val = ostree_bootconfig_parser_get (config, "options");
+ if (val)
+ g_ptr_array_add (new_lines, g_strdup_printf ("\tAPPEND %s", val));
+ }
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+static gboolean
+ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader,
+ int bootversion,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ OstreeBootloaderSyslinux *self = OSTREE_BOOTLOADER_SYSLINUX (bootloader);
+ gs_unref_object GFile *new_config_path = NULL;
+ gs_free char *config_contents = NULL;
+ gs_free char *new_config_contents = NULL;
+ gs_unref_ptrarray GPtrArray *new_lines = NULL;
+ gs_unref_ptrarray GPtrArray *tmp_lines = NULL;
+ gs_free char *kernel_arg = NULL;
+ gboolean saw_default = FALSE;
+ gboolean regenerate_default = FALSE;
+ gboolean parsing_label = FALSE;
+ char **lines = NULL;
+ char **iter;
+ guint i;
+
+ new_config_path = ot_gfile_resolve_path_printf (self->sysroot->path, "boot/loader.%d/syslinux.cfg",
+ bootversion);
+
+ /* This should follow the symbolic link to the current bootversion. */
+ config_contents = gs_file_load_contents_utf8 (self->config_path, cancellable, error);
+ if (!config_contents)
+ goto out;
+
+ lines = g_strsplit (config_contents, "\n", -1);
+ new_lines = g_ptr_array_new_with_free_func (g_free);
+ tmp_lines = g_ptr_array_new_with_free_func (g_free);
+
+ /* Note special iteration condition here; we want to also loop one
+ * more time at the end where line = NULL to ensure we finish off
+ * processing the last LABEL.
+ */
+ iter = lines;
+ while (TRUE)
+ {
+ char *line = *iter;
+ gboolean skip = FALSE;
+
+ if (parsing_label &&
+ (line == NULL || !g_str_has_prefix (line, "\t")))
+ {
+ parsing_label = FALSE;
+ if (kernel_arg == NULL)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "No KERNEL argument found after LABEL");
+ goto out;
+ }
+
+ /* If this is a non-ostree kernel, just emit the lines
+ * we saw.
+ */
+ if (!g_str_has_prefix (kernel_arg, "/ostree/"))
+ {
+ for (i = 0; i < tmp_lines->len; i++)
+ {
+ g_ptr_array_add (new_lines, tmp_lines->pdata[i]);
+ tmp_lines->pdata[i] = NULL; /* Transfer ownership */
+ }
+ }
+ else
+ {
+ /* Otherwise, we drop the config on the floor - it
+ * will be regenerated.
+ */
+ g_ptr_array_set_size (tmp_lines, 0);
+ }
+ }
+
+ if (line == NULL)
+ break;
+
+ if (!parsing_label &&
+ (g_str_has_prefix (line, "LABEL ")))
+ {
+ parsing_label = TRUE;
+ g_ptr_array_set_size (tmp_lines, 0);
+ }
+ else if (parsing_label && g_str_has_prefix (line, "\tKERNEL "))
+ {
+ g_free (kernel_arg);
+ kernel_arg = g_strdup (line + strlen ("\tKERNEL "));
+ }
+ else if (!parsing_label &&
+ (g_str_has_prefix (line, "DEFAULT ")))
+ {
+ saw_default = TRUE;
+ if (g_str_has_prefix (line, "DEFAULT ostree:"))
+ regenerate_default = TRUE;
+ skip = TRUE;
+ }
+
+ if (skip)
+ {
+ g_free (line);
+ }
+ else
+ {
+ if (parsing_label)
+ {
+ g_ptr_array_add (tmp_lines, line);
+ }
+ else
+ {
+ g_ptr_array_add (new_lines, line);
+ }
+ }
+ /* Transfer ownership */
+ *iter = NULL;
+ iter++;
+ }
+
+ if (!saw_default)
+ regenerate_default = TRUE;
+
+ if (!append_config_from_boostree_loader_entries (self, regenerate_default,
+ bootversion, new_lines,
+ cancellable, error))
+ goto out;
+
+ new_config_contents = _ostree_sysroot_join_lines (new_lines);
+
+ if (strcmp (new_config_contents, config_contents) != 0)
+ {
+ if (!g_file_replace_contents (new_config_path, new_config_contents,
+ strlen (new_config_contents),
+ NULL, FALSE, G_FILE_CREATE_NONE,
+ NULL, cancellable, error))
+ goto out;
+ g_print ("Saved new version of %s\n", gs_file_get_path_cached (self->config_path));
+ }
+
+ ret = TRUE;
+ out:
+ g_free (lines); /* Note we freed elements individually */
+ return ret;
+}
+
+static void
+ostree_bootloader_syslinux_finalize (GObject *object)
+{
+ OstreeBootloaderSyslinux *self = OSTREE_BOOTLOADER_SYSLINUX (object);
+
+ g_clear_object (&self->sysroot);
+ g_clear_object (&self->config_path);
+
+ G_OBJECT_CLASS (ostree_bootloader_syslinux_parent_class)->finalize (object);
+}
+
+void
+ostree_bootloader_syslinux_init (OstreeBootloaderSyslinux *self)
+{
+}
+
+static void
+ostree_bootloader_syslinux_bootloader_iface_init (OstreeBootloaderInterface *iface)
+{
+ iface->query = ostree_bootloader_syslinux_query;
+ iface->get_name = ostree_bootloader_syslinux_get_name;
+ iface->write_config = ostree_bootloader_syslinux_write_config;
+}
+
+void
+ostree_bootloader_syslinux_class_init (OstreeBootloaderSyslinuxClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->finalize = ostree_bootloader_syslinux_finalize;
+}
+
+OstreeBootloaderSyslinux *
+ostree_bootloader_syslinux_new (OstreeSysroot *sysroot)
+{
+ OstreeBootloaderSyslinux *self = g_object_new (OSTREE_TYPE_BOOTLOADER_SYSLINUX, NULL);
+ self->sysroot = g_object_ref (sysroot);
+ self->config_path = g_file_resolve_relative_path (self->sysroot->path, "boot/syslinux/syslinux.cfg");
+ return self;
+}
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2013 Colin Walters <walters@verbum.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include "ostree-bootloader.h"
+
+G_BEGIN_DECLS
+
+#define OSTREE_TYPE_BOOTLOADER_SYSLINUX (ostree_bootloader_syslinux_get_type ())
+#define OSTREE_BOOTLOADER_SYSLINUX(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), OSTREE_TYPE_BOOTLOADER_SYSLINUX, OstreeBootloaderSyslinux))
+#define OSTREE_IS_BOOTLOADER_SYSLINUX(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), OSTREE_TYPE_BOOTLOADER_SYSLINUX))
+
+typedef struct _OstreeBootloaderSyslinux OstreeBootloaderSyslinux;
+
+GType ostree_bootloader_syslinux_get_type (void) G_GNUC_CONST;
+
+OstreeBootloaderSyslinux * ostree_bootloader_syslinux_new (OstreeSysroot *sysroot);
+
+G_END_DECLS
+
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2013 Collabora Ltd
+ *
+ * Based on ot-bootloader-syslinux.c by Colin Walters <walters@verbum.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
+ */
+
+#include "config.h"
+
+#include "ostree-sysroot-private.h"
+#include "ostree-bootloader-uboot.h"
+#include "otutil.h"
+#include "libgsystem.h"
+
+#include <string.h>
+
+struct _OstreeBootloaderUboot
+{
+ GObject parent_instance;
+
+ OstreeSysroot *sysroot;
+ GFile *config_path;
+};
+
+typedef GObjectClass OstreeBootloaderUbootClass;
+
+static void ostree_bootloader_uboot_bootloader_iface_init (OstreeBootloaderInterface *iface);
+G_DEFINE_TYPE_WITH_CODE (OstreeBootloaderUboot, ostree_bootloader_uboot, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (OSTREE_TYPE_BOOTLOADER, ostree_bootloader_uboot_bootloader_iface_init));
+
+static gboolean
+ostree_bootloader_uboot_query (OstreeBootloader *bootloader)
+{
+ OstreeBootloaderUboot *self = OSTREE_BOOTLOADER_UBOOT (bootloader);
+
+ return g_file_query_file_type (self->config_path, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL) == G_FILE_TYPE_SYMBOLIC_LINK;
+}
+
+static const char *
+ostree_bootloader_uboot_get_name (OstreeBootloader *bootloader)
+{
+ return "U-Boot";
+}
+
+static gboolean
+create_config_from_boot_loader_entries (OstreeBootloaderUboot *self,
+ int bootversion,
+ GPtrArray *new_lines,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gs_unref_ptrarray GPtrArray *boot_loader_configs = NULL;
+ OstreeBootconfigParser *config;
+ const char *val;
+
+ if (!_ostree_sysroot_read_boot_loader_configs (self->sysroot, bootversion, &boot_loader_configs,
+ cancellable, error))
+ return FALSE;
+
+ /* U-Boot doesn't support a menu so just pick the first one since the list is ordered */
+ config = boot_loader_configs->pdata[0];
+
+ val = ostree_bootconfig_parser_get (config, "linux");
+ if (!val)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "No \"linux\" key in bootloader config");
+ return FALSE;
+ }
+ g_ptr_array_add (new_lines, g_strdup_printf ("kernel_image=%s", val));
+
+ val = ostree_bootconfig_parser_get (config, "initrd");
+ if (val)
+ g_ptr_array_add (new_lines, g_strdup_printf ("ramdisk_image=%s", val));
+
+ val = ostree_bootconfig_parser_get (config, "options");
+ if (val)
+ g_ptr_array_add (new_lines, g_strdup_printf ("bootargs=%s", val));
+
+ return TRUE;
+}
+
+static gboolean
+ostree_bootloader_uboot_write_config (OstreeBootloader *bootloader,
+ int bootversion,
+ GCancellable *cancellable,
+ GError **error)
+{
+ OstreeBootloaderUboot *self = OSTREE_BOOTLOADER_UBOOT (bootloader);
+ gs_unref_object GFile *new_config_path = NULL;
+ gs_free char *config_contents = NULL;
+ gs_free char *new_config_contents = NULL;
+ gs_unref_ptrarray GPtrArray *new_lines = NULL;
+
+ /* This should follow the symbolic link to the current bootversion. */
+ config_contents = gs_file_load_contents_utf8 (self->config_path, cancellable, error);
+ if (!config_contents)
+ return FALSE;
+
+ new_config_path = ot_gfile_resolve_path_printf (self->sysroot->path, "boot/loader.%d/uEnv.txt",
+ bootversion);
+
+ new_lines = g_ptr_array_new_with_free_func (g_free);
+
+ if (!create_config_from_boot_loader_entries (self, bootversion, new_lines,
+ cancellable, error))
+ return FALSE;
+
+ new_config_contents = _ostree_sysroot_join_lines (new_lines);
+
+ if (strcmp (new_config_contents, config_contents) != 0)
+ {
+ if (!g_file_replace_contents (new_config_path, new_config_contents,
+ strlen (new_config_contents),
+ NULL, FALSE, G_FILE_CREATE_NONE,
+ NULL, cancellable, error))
+ return FALSE;
+ g_print ("Saved new version of %s\n", gs_file_get_path_cached (self->config_path));
+ }
+
+ return TRUE;
+}
+
+static void
+ostree_bootloader_uboot_finalize (GObject *object)
+{
+ OstreeBootloaderUboot *self = OSTREE_BOOTLOADER_UBOOT (object);
+
+ g_clear_object (&self->sysroot);
+ g_clear_object (&self->config_path);
+
+ G_OBJECT_CLASS (ostree_bootloader_uboot_parent_class)->finalize (object);
+}
+
+void
+ostree_bootloader_uboot_init (OstreeBootloaderUboot *self)
+{
+}
+
+static void
+ostree_bootloader_uboot_bootloader_iface_init (OstreeBootloaderInterface *iface)
+{
+ iface->query = ostree_bootloader_uboot_query;
+ iface->get_name = ostree_bootloader_uboot_get_name;
+ iface->write_config = ostree_bootloader_uboot_write_config;
+}
+
+void
+ostree_bootloader_uboot_class_init (OstreeBootloaderUbootClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->finalize = ostree_bootloader_uboot_finalize;
+}
+
+OstreeBootloaderUboot *
+ostree_bootloader_uboot_new (OstreeSysroot *sysroot)
+{
+ OstreeBootloaderUboot *self = g_object_new (OSTREE_TYPE_BOOTLOADER_UBOOT, NULL);
+ self->sysroot = g_object_ref (sysroot);
+ self->config_path = g_file_resolve_relative_path (self->sysroot->path, "boot/uEnv.txt");
+ return self;
+}
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2013 Collabora Ltd
+ *
+ * Based on ot-bootloader-syslinux.h by Colin Walters <walters@verbum.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
+ */
+
+#pragma once
+
+#include "ostree-bootloader.h"
+
+G_BEGIN_DECLS
+
+#define OSTREE_TYPE_BOOTLOADER_UBOOT (ostree_bootloader_uboot_get_type ())
+#define OSTREE_BOOTLOADER_UBOOT(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), OSTREE_TYPE_BOOTLOADER_UBOOT, OstreeBootloaderUboot))
+#define OSTREE_IS_BOOTLOADER_UBOOT(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), OSTREE_TYPE_BOOTLOADER_UBOOT))
+
+typedef struct _OstreeBootloaderUboot OstreeBootloaderUboot;
+
+GType ostree_bootloader_uboot_get_type (void) G_GNUC_CONST;
+
+OstreeBootloaderUboot * ostree_bootloader_uboot_new (OstreeSysroot *sysroot);
+
+G_END_DECLS
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2013 Colin Walters <walters@verbum.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "ostree-bootloader.h"
+#include "libgsystem.h"
+
+G_DEFINE_INTERFACE (OstreeBootloader, ostree_bootloader, G_TYPE_OBJECT)
+
+static void
+ostree_bootloader_default_init (OstreeBootloaderInterface *iface)
+{
+}
+
+gboolean
+ostree_bootloader_query (OstreeBootloader *self)
+{
+ g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), FALSE);
+
+ return OSTREE_BOOTLOADER_GET_IFACE (self)->query (self);
+}
+
+/**
+ * ostree_bootloader_get_name:
+ *
+ * Returns: (transfer none): Name of this bootloader
+ */
+const char *
+ostree_bootloader_get_name (OstreeBootloader *self)
+{
+ g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), NULL);
+
+ return OSTREE_BOOTLOADER_GET_IFACE (self)->get_name (self);
+}
+
+gboolean
+ostree_bootloader_write_config (OstreeBootloader *self,
+ int bootversion,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), FALSE);
+
+ return OSTREE_BOOTLOADER_GET_IFACE (self)->write_config (self, bootversion,
+ cancellable, error);
+}
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2013 Colin Walters <walters@verbum.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define OSTREE_TYPE_BOOTLOADER (ostree_bootloader_get_type ())
+#define OSTREE_BOOTLOADER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), OSTREE_TYPE_BOOTLOADER, OstreeBootloader))
+#define OSTREE_IS_BOOTLOADER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), OSTREE_TYPE_BOOTLOADER))
+#define OSTREE_BOOTLOADER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), OSTREE_TYPE_BOOTLOADER, OstreeBootloaderInterface))
+
+typedef struct _OstreeBootloader OstreeBootloader;
+typedef struct _OstreeBootloaderInterface OstreeBootloaderInterface;
+
+struct _OstreeBootloaderInterface
+{
+ GTypeInterface g_iface;
+
+ /* virtual functions */
+ gboolean (* query) (OstreeBootloader *self);
+ const char * (* get_name) (OstreeBootloader *self);
+ gboolean (* write_config) (OstreeBootloader *self,
+ int bootversion,
+ GCancellable *cancellable,
+ GError **error);
+};
+
+GType ostree_bootloader_get_type (void) G_GNUC_CONST;
+
+gboolean ostree_bootloader_query (OstreeBootloader *self);
+
+const char *ostree_bootloader_get_name (OstreeBootloader *self);
+
+gboolean ostree_bootloader_write_config (OstreeBootloader *self,
+ int bootversion,
+ GCancellable *cancellable,
+ GError **error);
+
+G_END_DECLS
+
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2013 Colin Walters <walters@verbum.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "otutil.h"
+#include "libgsystem.h"
+
+#include "ostree-sysroot-private.h"
+
+static gboolean
+list_deployment_dirs_for_os (GFile *osdir,
+ GPtrArray *inout_deployments,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ const char *osname = gs_file_get_basename_cached (osdir);
+ gs_unref_object GFileEnumerator *dir_enum = NULL;
+ gs_unref_object GFile *osdeploy_dir = NULL;
+ GError *temp_error = NULL;
+
+ osdeploy_dir = g_file_get_child (osdir, "deploy");
+
+ dir_enum = g_file_enumerate_children (osdeploy_dir, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, &temp_error);
+ if (!dir_enum)
+ {
+ if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ {
+ g_clear_error (&temp_error);
+ goto done;
+ }
+ else
+ {
+ g_propagate_error (error, temp_error);
+ goto out;
+ }
+ }
+
+ while (TRUE)
+ {
+ const char *name;
+ GFileInfo *file_info = NULL;
+ GFile *child = NULL;
+ gs_unref_object OstreeDeployment *deployment = NULL;
+ gs_free char *csum = NULL;
+ gint deployserial;
+
+ if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
+ cancellable, error))
+ goto out;
+ if (file_info == NULL)
+ break;
+
+ name = g_file_info_get_name (file_info);
+
+ if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
+ continue;
+
+ if (!_ostree_sysroot_parse_deploy_path_name (name, &csum, &deployserial, error))
+ goto out;
+
+ deployment = ostree_deployment_new (-1, osname, csum, deployserial, NULL, -1);
+ g_ptr_array_add (inout_deployments, g_object_ref (deployment));
+ }
+
+ done:
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+static gboolean
+list_all_deployment_directories (OstreeSysroot *self,
+ GPtrArray **out_deployments,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_object GFileEnumerator *dir_enum = NULL;
+ gs_unref_object GFile *deploydir = NULL;
+ gs_unref_ptrarray GPtrArray *ret_deployments = NULL;
+ GError *temp_error = NULL;
+
+ deploydir = g_file_resolve_relative_path (self->path, "ostree/deploy");
+
+ ret_deployments = g_ptr_array_new_with_free_func (g_object_unref);
+
+ dir_enum = g_file_enumerate_children (deploydir, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, &temp_error);
+ if (!dir_enum)
+ {
+ if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ {
+ g_clear_error (&temp_error);
+ goto done;
+ }
+ else
+ {
+ g_propagate_error (error, temp_error);
+ goto out;
+ }
+ }
+
+ while (TRUE)
+ {
+ GFileInfo *file_info = NULL;
+ GFile *child = NULL;
+
+ if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
+ NULL, error))
+ goto out;
+ if (file_info == NULL)
+ break;
+
+ if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
+ continue;
+
+ if (!list_deployment_dirs_for_os (child, ret_deployments, cancellable, error))
+ goto out;
+ }
+
+ done:
+ ret = TRUE;
+ ot_transfer_out_value (out_deployments, &ret_deployments);
+ out:
+ return ret;
+}
+
+static gboolean
+parse_bootdir_name (const char *name,
+ char **out_osname,
+ char **out_csum)
+{
+ const char *lastdash;
+
+ if (out_osname)
+ *out_osname = NULL;
+ if (out_csum)
+ *out_csum = NULL;
+
+ lastdash = strrchr (name, '-');
+
+ if (!lastdash)
+ return FALSE;
+
+ if (!ostree_validate_checksum_string (lastdash + 1, NULL))
+ return FALSE;
+
+ if (out_osname)
+ *out_osname = g_strndup (name, lastdash - name);
+ if (out_csum)
+ *out_csum = g_strdup (lastdash + 1);
+
+ return TRUE;
+}
+
+static gboolean
+list_all_boot_directories (OstreeSysroot *self,
+ GPtrArray **out_bootdirs,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_object GFileEnumerator *dir_enum = NULL;
+ gs_unref_object GFile *boot_ostree = NULL;
+ gs_unref_ptrarray GPtrArray *ret_bootdirs = NULL;
+ GError *temp_error = NULL;
+
+ boot_ostree = g_file_resolve_relative_path (self->path, "boot/ostree");
+
+ ret_bootdirs = g_ptr_array_new_with_free_func (g_object_unref);
+
+ dir_enum = g_file_enumerate_children (boot_ostree, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, &temp_error);
+ if (!dir_enum)
+ {
+ if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ {
+ g_clear_error (&temp_error);
+ goto done;
+ }
+ else
+ {
+ g_propagate_error (error, temp_error);
+ goto out;
+ }
+ }
+
+ while (TRUE)
+ {
+ GFileInfo *file_info = NULL;
+ GFile *child = NULL;
+ const char *name;
+
+ if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
+ NULL, error))
+ goto out;
+ if (file_info == NULL)
+ break;
+
+ if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
+ continue;
+
+ /* Only look at directories ending in -CHECKSUM; nothing else
+ * should be in here, but let's be conservative.
+ */
+ name = g_file_info_get_name (file_info);
+ if (!parse_bootdir_name (name, NULL, NULL))
+ continue;
+
+ g_ptr_array_add (ret_bootdirs, g_object_ref (child));
+ }
+
+ done:
+ ret = TRUE;
+ ot_transfer_out_value (out_bootdirs, &ret_bootdirs);
+ out:
+ return ret;
+}
+
+static gboolean
+cleanup_other_bootversions (OstreeSysroot *self,
+ int bootversion,
+ int subbootversion,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ int cleanup_bootversion;
+ int cleanup_subbootversion;
+ gs_unref_object GFile *cleanup_boot_dir = NULL;
+
+ cleanup_bootversion = bootversion == 0 ? 1 : 0;
+ cleanup_subbootversion = subbootversion == 0 ? 1 : 0;
+
+ cleanup_boot_dir = ot_gfile_resolve_path_printf (self->path, "boot/loader.%d", cleanup_bootversion);
+ if (!gs_shutil_rm_rf (cleanup_boot_dir, cancellable, error))
+ goto out;
+ g_clear_object (&cleanup_boot_dir);
+
+ cleanup_boot_dir = ot_gfile_resolve_path_printf (self->path, "ostree/boot.%d", cleanup_bootversion);
+ if (!gs_shutil_rm_rf (cleanup_boot_dir, cancellable, error))
+ goto out;
+ g_clear_object (&cleanup_boot_dir);
+
+ cleanup_boot_dir = ot_gfile_resolve_path_printf (self->path, "ostree/boot.%d.0", cleanup_bootversion);
+ if (!gs_shutil_rm_rf (cleanup_boot_dir, cancellable, error))
+ goto out;
+ g_clear_object (&cleanup_boot_dir);
+
+ cleanup_boot_dir = ot_gfile_resolve_path_printf (self->path, "ostree/boot.%d.1", cleanup_bootversion);
+ if (!gs_shutil_rm_rf (cleanup_boot_dir, cancellable, error))
+ goto out;
+ g_clear_object (&cleanup_boot_dir);
+
+ cleanup_boot_dir = ot_gfile_resolve_path_printf (self->path, "ostree/boot.%d.%d", bootversion,
+ cleanup_subbootversion);
+ if (!gs_shutil_rm_rf (cleanup_boot_dir, cancellable, error))
+ goto out;
+ g_clear_object (&cleanup_boot_dir);
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+static gboolean
+cleanup_old_deployments (OstreeSysroot *self,
+ GPtrArray *deployments,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ guint32 root_device;
+ guint64 root_inode;
+ guint i;
+ gs_unref_object GFile *active_root = g_file_new_for_path ("/");
+ gs_unref_hashtable GHashTable *active_deployment_dirs = NULL;
+ gs_unref_hashtable GHashTable *active_boot_checksums = NULL;
+ gs_unref_ptrarray GPtrArray *all_deployment_dirs = NULL;
+ gs_unref_ptrarray GPtrArray *all_boot_dirs = NULL;
+
+ if (!_ostree_sysroot_get_devino (active_root, &root_device, &root_inode,
+ cancellable, error))
+ goto out;
+
+ active_deployment_dirs = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, NULL, g_object_unref);
+ active_boot_checksums = g_hash_table_new_full (g_str_hash, (GEqualFunc)g_str_equal, g_free, NULL);
+
+ for (i = 0; i < deployments->len; i++)
+ {
+ OstreeDeployment *deployment = deployments->pdata[i];
+ GFile *deployment_path = ostree_sysroot_get_deployment_directory (self, deployment);
+ char *bootcsum = g_strdup (ostree_deployment_get_bootcsum (deployment));
+ /* Transfer ownership */
+ g_hash_table_insert (active_deployment_dirs, deployment_path, deployment_path);
+ g_hash_table_insert (active_boot_checksums, bootcsum, bootcsum);
+ }
+
+ if (!list_all_deployment_directories (self, &all_deployment_dirs,
+ cancellable, error))
+ goto out;
+
+ for (i = 0; i < all_deployment_dirs->len; i++)
+ {
+ OstreeDeployment *deployment = all_deployment_dirs->pdata[i];
+ gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (self, deployment);
+ gs_unref_object GFile *origin_path = ostree_sysroot_get_deployment_origin_path (deployment_path);
+ if (!g_hash_table_lookup (active_deployment_dirs, deployment_path))
+ {
+ guint32 device;
+ guint64 inode;
+
+ if (!_ostree_sysroot_get_devino (deployment_path, &device, &inode,
+ cancellable, error))
+ goto out;
+
+ /* This shouldn't happen, because higher levels should
+ * disallow having the booted deployment not in the active
+ * deployment list, but let's be extra safe. */
+ if (device == root_device && inode == root_inode)
+ continue;
+
+ g_print ("ostadmin: Deleting deployment %s\n", gs_file_get_path_cached (deployment_path));
+ if (!gs_shutil_rm_rf (deployment_path, cancellable, error))
+ goto out;
+ if (!gs_shutil_rm_rf (origin_path, cancellable, error))
+ goto out;
+ }
+ }
+
+ if (!list_all_boot_directories (self, &all_boot_dirs,
+ cancellable, error))
+ goto out;
+
+ for (i = 0; i < all_boot_dirs->len; i++)
+ {
+ GFile *bootdir = all_boot_dirs->pdata[i];
+ gs_free char *osname = NULL;
+ gs_free char *bootcsum = NULL;
+
+ if (!parse_bootdir_name (gs_file_get_basename_cached (bootdir),
+ &osname, &bootcsum))
+ g_assert_not_reached ();
+
+ if (g_hash_table_lookup (active_boot_checksums, bootcsum))
+ continue;
+
+ g_print ("ostadmin: Deleting bootdir %s\n", gs_file_get_path_cached (bootdir));
+ if (!gs_shutil_rm_rf (bootdir, cancellable, error))
+ goto out;
+ }
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+static gboolean
+cleanup_ref_prefix (OstreeRepo *repo,
+ int bootversion,
+ int subbootversion,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_free char *prefix = NULL;
+ gs_unref_hashtable GHashTable *refs = NULL;
+ GHashTableIter hashiter;
+ gpointer hashkey, hashvalue;
+
+ prefix = g_strdup_printf ("ostree/%d/%d", bootversion, subbootversion);
+
+ if (!ostree_repo_list_refs (repo, prefix, &refs, cancellable, error))
+ goto out;
+
+ if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
+ goto out;
+
+ g_hash_table_iter_init (&hashiter, refs);
+ while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))
+ {
+ const char *suffix = hashkey;
+ gs_free char *ref = g_strconcat (prefix, "/", suffix, NULL);
+ ostree_repo_transaction_set_refspec (repo, ref, NULL);
+ }
+
+ if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))
+ goto out;
+
+ ret = TRUE;
+ out:
+ ostree_repo_abort_transaction (repo, cancellable, NULL);
+ return ret;
+}
+
+static gboolean
+generate_deployment_refs_and_prune (OstreeSysroot *self,
+ OstreeRepo *repo,
+ int bootversion,
+ int subbootversion,
+ GPtrArray *deployments,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ int cleanup_bootversion;
+ int cleanup_subbootversion;
+ guint i;
+ gint n_objects_total, n_objects_pruned;
+ guint64 freed_space;
+
+ cleanup_bootversion = (bootversion == 0) ? 1 : 0;
+ cleanup_subbootversion = (subbootversion == 0) ? 1 : 0;
+
+ if (!cleanup_ref_prefix (repo, cleanup_bootversion, 0,
+ cancellable, error))
+ goto out;
+
+ if (!cleanup_ref_prefix (repo, cleanup_bootversion, 1,
+ cancellable, error))
+ goto out;
+
+ if (!cleanup_ref_prefix (repo, bootversion, cleanup_subbootversion,
+ cancellable, error))
+ goto out;
+
+ for (i = 0; i < deployments->len; i++)
+ {
+ OstreeDeployment *deployment = deployments->pdata[i];
+ gs_free char *refname = g_strdup_printf ("ostree/%d/%d/%u",
+ bootversion, subbootversion,
+ i);
+
+ if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
+ goto out;
+
+ ostree_repo_transaction_set_refspec (repo, refname, ostree_deployment_get_csum (deployment));
+
+ if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))
+ goto out;
+ }
+
+ if (!ostree_repo_prune (repo, OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY, 0,
+ &n_objects_total, &n_objects_pruned, &freed_space,
+ cancellable, error))
+ goto out;
+ if (freed_space > 0)
+ {
+ char *freed_space_str = g_format_size_full (freed_space, 0);
+ g_print ("Freed objects: %s\n", freed_space_str);
+ }
+
+ ret = TRUE;
+ out:
+ ostree_repo_abort_transaction (repo, cancellable, NULL);
+ return ret;
+}
+
+/**
+ * ostree_sysroot_cleanup:
+ * @self: Sysroot
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Delete any state that resulted from a partially completed
+ * transaction, such as incomplete deployments.
+ */
+gboolean
+ostree_sysroot_cleanup (OstreeSysroot *self,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_ptrarray GPtrArray *deployments = NULL;
+ gs_unref_object OstreeRepo *repo = NULL;
+ int bootversion;
+ int subbootversion;
+
+ if (!ostree_sysroot_list_deployments (self, &bootversion, &deployments,
+ cancellable, error))
+ goto out;
+
+ if (!ostree_sysroot_read_current_subbootversion (self, bootversion, &subbootversion,
+ cancellable, error))
+ goto out;
+
+ if (!cleanup_other_bootversions (self, bootversion, subbootversion,
+ cancellable, error))
+ goto out;
+
+ if (!cleanup_old_deployments (self, deployments,
+ cancellable, error))
+ goto out;
+
+ if (deployments->len > 0)
+ {
+ if (!ostree_sysroot_get_repo (self, &repo, cancellable, error))
+ goto out;
+
+ if (!generate_deployment_refs_and_prune (self, repo, bootversion,
+ subbootversion, deployments,
+ cancellable, error))
+ goto out;
+ }
+
+ ret = TRUE;
+ out:
+ return ret;
+}
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012,2013 Colin Walters <walters@verbum.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include "ostree.h"
+
+G_BEGIN_DECLS
+
+struct OstreeSysroot {
+ GObject parent;
+
+ GFile *path;
+ int sysroot_fd;
+};
+
+gboolean
+_ostree_sysroot_read_boot_loader_configs (OstreeSysroot *self,
+ int bootversion,
+ GPtrArray **out_loader_configs,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean
+_ostree_sysroot_parse_deploy_path_name (const char *name,
+ char **out_csum,
+ int *out_serial,
+ GError **error);
+
+gboolean
+_ostree_sysroot_get_devino (GFile *path,
+ guint32 *out_device,
+ guint64 *out_inode,
+ GCancellable *cancellable,
+ GError **error);
+
+char *_ostree_sysroot_join_lines (GPtrArray *lines);
+
+G_END_DECLS
+
#include "otutil.h"
#include "libgsystem.h"
-#include "ostree-sysroot.h"
+#include "ostree-sysroot-private.h"
+#include "ostree-bootloader-uboot.h"
+#include "ostree-bootloader-syslinux.h"
/**
* SECTION:libostree-sysroot
* Inside this directory is an #OstreeRepo in /ostree/repo, plus a set
* of deployments in /ostree/deploy.
*/
-
-struct OstreeSysroot {
- GObject parent;
-
- GFile *path;
- int sysroot_fd;
-};
-
typedef struct {
GObjectClass parent_class;
} OstreeSysrootClass;
return self->path;
}
+gboolean
+_ostree_sysroot_get_devino (GFile *path,
+ guint32 *out_device,
+ guint64 *out_inode,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_object GFileInfo *finfo = g_file_query_info (path, "unix::device,unix::inode",
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, error);
+
+ if (!finfo)
+ goto out;
+
+ ret = TRUE;
+ *out_device = g_file_info_get_attribute_uint32 (finfo, "unix::device");
+ *out_inode = g_file_info_get_attribute_uint64 (finfo, "unix::inode");
+ out:
+ return ret;
+}
+
/**
* ostree_sysroot_ensure_initialized:
* @self:
out:
return ret;
}
+
+static void
+match_info_cleanup (void *loc)
+{
+ GMatchInfo **match = (GMatchInfo**)loc;
+ if (*match) g_match_info_unref (*match);
+}
+
+gboolean
+_ostree_sysroot_parse_deploy_path_name (const char *name,
+ char **out_csum,
+ int *out_serial,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ __attribute__((cleanup(match_info_cleanup))) GMatchInfo *match = NULL;
+ gs_free char *serial_str = NULL;
+
+ static gsize regex_initialized;
+ static GRegex *regex;
+
+ if (g_once_init_enter (®ex_initialized))
+ {
+ regex = g_regex_new ("^([0-9a-f]+)\\.([0-9]+)$", 0, 0, NULL);
+ g_assert (regex);
+ g_once_init_leave (®ex_initialized, 1);
+ }
+
+ if (!g_regex_match (regex, name, 0, &match))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid deploy name '%s', expected CHECKSUM.TREESERIAL", name);
+ goto out;
+ }
+
+ *out_csum = g_match_info_fetch (match, 1);
+ serial_str = g_match_info_fetch (match, 2);
+ *out_serial = (int)g_ascii_strtoll (serial_str, NULL, 10);
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+
+/**
+ * ostree_sysroot_read_current_subbootversion:
+ * @self: Sysroot
+ * @bootversion: Current boot version
+ * @out_subbootversion: (out): The active subbootversion
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Determine the active subbootversion.
+ */
+gboolean
+ostree_sysroot_read_current_subbootversion (OstreeSysroot *self,
+ int bootversion,
+ int *out_subbootversion,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_object GFile *ostree_dir = g_file_get_child (self->path, "ostree");
+ gs_free char *ostree_bootdir_name = g_strdup_printf ("boot.%d", bootversion);
+ gs_unref_object GFile *ostree_bootdir = g_file_resolve_relative_path (ostree_dir, ostree_bootdir_name);
+ gs_unref_object GFile *ostree_subbootdir = NULL;
+
+ if (!ot_gfile_query_symlink_target_allow_noent (ostree_bootdir, &ostree_subbootdir,
+ cancellable, error))
+ goto out;
+
+ if (ostree_subbootdir == NULL)
+ {
+ *out_subbootversion = 0;
+ }
+ else
+ {
+ const char *current_subbootdir_name = gs_file_get_basename_cached (ostree_subbootdir);
+ if (g_str_has_suffix (current_subbootdir_name, ".0"))
+ *out_subbootversion = 0;
+ else if (g_str_has_suffix (current_subbootdir_name, ".1"))
+ *out_subbootversion = 1;
+ else
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid target '%s' in %s",
+ gs_file_get_path_cached (ostree_subbootdir),
+ gs_file_get_path_cached (ostree_bootdir));
+ goto out;
+ }
+ }
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+gboolean
+_ostree_sysroot_read_boot_loader_configs (OstreeSysroot *self,
+ int bootversion,
+ GPtrArray **out_loader_configs,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_object GFileEnumerator *dir_enum = NULL;
+ gs_unref_object GFile *loader_entries_dir = NULL;
+ gs_unref_ptrarray GPtrArray *ret_loader_configs = NULL;
+ GError *temp_error = NULL;
+
+ loader_entries_dir = ot_gfile_resolve_path_printf (self->path, "boot/loader.%d/entries",
+ bootversion);
+ ret_loader_configs = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
+
+ dir_enum = g_file_enumerate_children (loader_entries_dir, OSTREE_GIO_FAST_QUERYINFO,
+ 0, NULL, &temp_error);
+ if (!dir_enum)
+ {
+ if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ {
+ g_clear_error (&temp_error);
+ goto done;
+ }
+ else
+ {
+ g_propagate_error (error, temp_error);
+ goto out;
+ }
+ }
+
+ while (TRUE)
+ {
+ GFileInfo *file_info;
+ GFile *child;
+ const char *name;
+
+ if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
+ cancellable, error))
+ goto out;
+ if (file_info == NULL)
+ break;
+
+ name = g_file_info_get_name (file_info);
+
+ if (g_str_has_prefix (name, "ostree-") &&
+ g_str_has_suffix (name, ".conf") &&
+ g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
+ {
+ gs_unref_object OstreeBootconfigParser *config = ostree_bootconfig_parser_new ();
+
+ if (!ostree_bootconfig_parser_parse (config, child, cancellable, error))
+ {
+ g_prefix_error (error, "Parsing %s: ", gs_file_get_path_cached (child));
+ goto out;
+ }
+
+ g_ptr_array_add (ret_loader_configs, g_object_ref (config));
+ }
+ }
+
+ done:
+ gs_transfer_out_value (out_loader_configs, &ret_loader_configs);
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+
+static gboolean
+read_current_bootversion (OstreeSysroot *self,
+ int *out_bootversion,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_object GFile *boot_loader_path = g_file_resolve_relative_path (self->path, "boot/loader");
+ gs_unref_object GFileInfo *info = NULL;
+ const char *target;
+ int ret_bootversion;
+
+ if (!ot_gfile_query_info_allow_noent (boot_loader_path, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ &info,
+ cancellable, error))
+ goto out;
+
+ if (info == NULL)
+ ret_bootversion = 0;
+ else
+ {
+ if (g_file_info_get_file_type (info) != G_FILE_TYPE_SYMBOLIC_LINK)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Not a symbolic link: %s", gs_file_get_path_cached (boot_loader_path));
+ goto out;
+ }
+
+ target = g_file_info_get_symlink_target (info);
+ if (g_strcmp0 (target, "loader.0") == 0)
+ ret_bootversion = 0;
+ else if (g_strcmp0 (target, "loader.1") == 0)
+ ret_bootversion = 1;
+ else
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid target '%s' in %s", target, gs_file_get_path_cached (boot_loader_path));
+ goto out;
+ }
+ }
+
+ ret = TRUE;
+ *out_bootversion = ret_bootversion;
+ out:
+ return ret;
+}
+
+static gboolean
+parse_origin (OstreeSysroot *self,
+ GFile *deployment_path,
+ GKeyFile **out_origin,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GKeyFile *ret_origin = NULL;
+ gs_unref_object GFile *origin_path = ostree_sysroot_get_deployment_origin_path (deployment_path);
+ gs_free char *origin_contents = NULL;
+
+ if (!ot_gfile_load_contents_utf8_allow_noent (origin_path, &origin_contents,
+ cancellable, error))
+ goto out;
+
+ if (origin_contents)
+ {
+ ret_origin = g_key_file_new ();
+ if (!g_key_file_load_from_data (ret_origin, origin_contents, -1, 0, error))
+ goto out;
+ }
+
+ ret = TRUE;
+ gs_transfer_out_value (out_origin, &ret_origin);
+ out:
+ if (error)
+ g_prefix_error (error, "Parsing %s: ", gs_file_get_path_cached (origin_path));
+ if (ret_origin)
+ g_key_file_unref (ret_origin);
+ return ret;
+}
+
+static gboolean
+parse_bootlink (const char *bootlink,
+ int *out_entry_bootversion,
+ char **out_osname,
+ char **out_bootcsum,
+ int *out_treebootserial,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ __attribute__((cleanup(match_info_cleanup))) GMatchInfo *match = NULL;
+ gs_free char *bootversion_str = NULL;
+ gs_free char *treebootserial_str = NULL;
+
+ static gsize regex_initialized;
+ static GRegex *regex;
+
+ if (g_once_init_enter (®ex_initialized))
+ {
+ regex = g_regex_new ("^/ostree/boot.([01])/([^/]+)/([^/]+)/([0-9]+)$", 0, 0, NULL);
+ g_assert (regex);
+ g_once_init_leave (®ex_initialized, 1);
+ }
+
+ if (!g_regex_match (regex, bootlink, 0, &match))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid ostree= argument '%s', expected ostree=/ostree/boot.BOOTVERSION/OSNAME/BOOTCSUM/TREESERIAL", bootlink);
+ goto out;
+ }
+
+ bootversion_str = g_match_info_fetch (match, 1);
+ *out_entry_bootversion = (int)g_ascii_strtoll (bootversion_str, NULL, 10);
+ *out_osname = g_match_info_fetch (match, 2);
+ *out_bootcsum = g_match_info_fetch (match, 3);
+ treebootserial_str = g_match_info_fetch (match, 4);
+ *out_treebootserial = (int)g_ascii_strtoll (treebootserial_str, NULL, 10);
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+static gboolean
+parse_deployment (OstreeSysroot *self,
+ const char *boot_link,
+ OstreeDeployment **out_deployment,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ const char *relative_boot_link;
+ gs_unref_object OstreeDeployment *ret_deployment = NULL;
+ int entry_boot_version;
+ int treebootserial = -1;
+ int deployserial = -1;
+ gs_free char *osname = NULL;
+ gs_free char *bootcsum = NULL;
+ gs_free char *treecsum = NULL;
+ gs_unref_object GFile *treebootserial_link = NULL;
+ gs_unref_object GFileInfo *treebootserial_info = NULL;
+ gs_unref_object GFile *treebootserial_target = NULL;
+ GKeyFile *origin = NULL;
+
+ if (!parse_bootlink (boot_link, &entry_boot_version,
+ &osname, &bootcsum, &treebootserial,
+ error))
+ goto out;
+
+ relative_boot_link = boot_link;
+ if (*relative_boot_link == '/')
+ relative_boot_link++;
+ treebootserial_link = g_file_resolve_relative_path (self->path, relative_boot_link);
+ treebootserial_info = g_file_query_info (treebootserial_link, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, error);
+ if (!treebootserial_info)
+ goto out;
+
+ if (!ot_gfile_get_symlink_target_from_info (treebootserial_link, treebootserial_info,
+ &treebootserial_target, cancellable, error))
+ goto out;
+
+ if (!_ostree_sysroot_parse_deploy_path_name (gs_file_get_basename_cached (treebootserial_target),
+ &treecsum, &deployserial, error))
+ goto out;
+
+ if (!parse_origin (self, treebootserial_target, &origin,
+ cancellable, error))
+ goto out;
+
+ ret_deployment = ostree_deployment_new (-1, osname, treecsum, deployserial,
+ bootcsum, treebootserial);
+ if (origin)
+ ostree_deployment_set_origin (ret_deployment, origin);
+
+ ret = TRUE;
+ gs_transfer_out_value (out_deployment, &ret_deployment);
+ out:
+ if (origin)
+ g_key_file_unref (origin);
+ return ret;
+}
+
+static char *
+get_ostree_kernel_arg_from_config (OstreeBootconfigParser *config)
+{
+ const char *options;
+ char *ret = NULL;
+ char **opts, **iter;
+
+ options = ostree_bootconfig_parser_get (config, "options");
+ if (!options)
+ return NULL;
+
+ opts = g_strsplit (options, " ", -1);
+ for (iter = opts; *iter; iter++)
+ {
+ const char *opt = *iter;
+ if (g_str_has_prefix (opt, "ostree="))
+ {
+ ret = g_strdup (opt + strlen ("ostree="));
+ break;
+ }
+ }
+ g_strfreev (opts);
+
+ return ret;
+}
+
+static gboolean
+list_deployments_process_one_boot_entry (OstreeSysroot *self,
+ OstreeBootconfigParser *config,
+ GPtrArray *inout_deployments,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_free char *ostree_arg = NULL;
+ gs_unref_object OstreeDeployment *deployment = NULL;
+
+ ostree_arg = get_ostree_kernel_arg_from_config (config);
+ if (ostree_arg == NULL)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "No ostree= kernel argument found");
+ goto out;
+ }
+
+ if (!parse_deployment (self, ostree_arg, &deployment,
+ cancellable, error))
+ goto out;
+
+ ostree_deployment_set_bootconfig (deployment, config);
+
+ g_ptr_array_add (inout_deployments, g_object_ref (deployment));
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+static gint
+compare_deployments_by_boot_loader_version_reversed (gconstpointer a_pp,
+ gconstpointer b_pp)
+{
+ OstreeDeployment *a = *((OstreeDeployment**)a_pp);
+ OstreeDeployment *b = *((OstreeDeployment**)b_pp);
+ OstreeBootconfigParser *a_bootconfig = ostree_deployment_get_bootconfig (a);
+ OstreeBootconfigParser *b_bootconfig = ostree_deployment_get_bootconfig (b);
+ const char *a_version = ostree_bootconfig_parser_get (a_bootconfig, "version");
+ const char *b_version = ostree_bootconfig_parser_get (b_bootconfig, "version");
+
+ if (a_version && b_version)
+ {
+ int r = strverscmp (a_version, b_version);
+ /* Reverse */
+ return -r;
+ }
+ else if (a_version)
+ return -1;
+ else
+ return 1;
+}
+/**
+ * ostree_sysroot_list_deployments:
+ * @sysroot: Sysroot
+ * @out_current_bootversion: (out): Current bootversion
+ * @out_deployments: (out) (element-type OstreeDeployment): Deployment list
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Enumerate all deployments, in the boot order. Also returns the
+ * active bootversion.
+ */
+gboolean
+ostree_sysroot_list_deployments (OstreeSysroot *self,
+ int *out_current_bootversion,
+ GPtrArray **out_deployments,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_ptrarray GPtrArray *boot_loader_configs = NULL;
+ gs_unref_ptrarray GPtrArray *ret_deployments = NULL;
+ guint i;
+ int bootversion = -1;
+
+ if (!read_current_bootversion (self, &bootversion, cancellable, error))
+ goto out;
+
+ if (!_ostree_sysroot_read_boot_loader_configs (self, bootversion, &boot_loader_configs,
+ cancellable, error))
+ goto out;
+
+ ret_deployments = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
+
+ for (i = 0; i < boot_loader_configs->len; i++)
+ {
+ OstreeBootconfigParser *config = boot_loader_configs->pdata[i];
+
+ if (!list_deployments_process_one_boot_entry (self, config, ret_deployments,
+ cancellable, error))
+ goto out;
+ }
+
+ g_ptr_array_sort (ret_deployments, compare_deployments_by_boot_loader_version_reversed);
+ for (i = 0; i < ret_deployments->len; i++)
+ {
+ OstreeDeployment *deployment = ret_deployments->pdata[i];
+ ostree_deployment_set_index (deployment, i);
+ }
+
+ ret = TRUE;
+ *out_current_bootversion = bootversion;
+ gs_transfer_out_value (out_deployments, &ret_deployments);
+ out:
+ return ret;
+}
+
+/**
+ * ostree_sysroot_get_deployment_directory:
+ * @self: Sysroot
+ * @deployment: A deployment
+ *
+ * Returns: (transfer full): Path to deployment root directory
+ */
+GFile *
+ostree_sysroot_get_deployment_directory (OstreeSysroot *self,
+ OstreeDeployment *deployment)
+{
+ gs_free char *path = g_strdup_printf ("ostree/deploy/%s/deploy/%s.%d",
+ ostree_deployment_get_osname (deployment),
+ ostree_deployment_get_csum (deployment),
+ ostree_deployment_get_deployserial (deployment));
+ return g_file_resolve_relative_path (self->path, path);
+}
+
+/**
+ * ostree_sysroot_get_deployment_origin_path:
+ * @self: Sysroot
+ * @deployment: A deployment
+ *
+ * Returns: (transfer full): Path to deployment origin file
+ */
+GFile *
+ostree_sysroot_get_deployment_origin_path (GFile *deployment_path)
+{
+ gs_unref_object GFile *deployment_parent = g_file_get_parent (deployment_path);
+ return ot_gfile_resolve_path_printf (deployment_parent,
+ "%s.origin",
+ gs_file_get_path_cached (deployment_path));
+}
+
+
+/**
+ * ostree_sysroot_get_repo:
+ * @self: Sysroot
+ * @out_repo: (out): Repository in sysroot @self
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Retrieve the OSTree repository in sysroot @self.
+ */
+gboolean
+ostree_sysroot_get_repo (OstreeSysroot *self,
+ OstreeRepo **out_repo,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_object OstreeRepo *ret_repo = NULL;
+ gs_unref_object GFile *repo_path = g_file_resolve_relative_path (self->path, "ostree/repo");
+
+ ret_repo = ostree_repo_new (repo_path);
+ if (!ostree_repo_open (ret_repo, cancellable, error))
+ goto out;
+
+ ret = TRUE;
+ ot_transfer_out_value (out_repo, &ret_repo);
+ out:
+ return ret;
+}
+
+
+/**
+ * ostree_sysroot_query_bootloader:
+ * @sysroot: Sysroot
+ *
+ * Returns: (transfer full): Currently active bootloader in @sysroot
+ */
+OstreeBootloader *
+ostree_sysroot_query_bootloader (OstreeSysroot *self)
+{
+ OstreeBootloaderSyslinux *syslinux;
+ OstreeBootloaderUboot *uboot;
+
+ syslinux = ostree_bootloader_syslinux_new (self);
+ if (ostree_bootloader_query ((OstreeBootloader*)syslinux))
+ return (OstreeBootloader*) (syslinux);
+
+ uboot = ostree_bootloader_uboot_new (self);
+ if (ostree_bootloader_query ((OstreeBootloader*)uboot))
+ return (OstreeBootloader*) (uboot);
+
+ return NULL;
+}
+
+char *
+_ostree_sysroot_join_lines (GPtrArray *lines)
+{
+ GString *buf = g_string_new ("");
+ guint i;
+ gboolean prev_was_empty = FALSE;
+
+ for (i = 0; i < lines->len; i++)
+ {
+ const char *line = lines->pdata[i];
+ /* Special bit to remove extraneous empty lines */
+ if (*line == '\0')
+ {
+ if (prev_was_empty || i == 0)
+ continue;
+ else
+ prev_was_empty = TRUE;
+ }
+ g_string_append (buf, line);
+ g_string_append_c (buf, '\n');
+ }
+ return g_string_free (buf, FALSE);
+}
#pragma once
#include "ostree-repo.h"
+#include "ostree-deployment.h"
+#include "ostree-bootloader.h"
G_BEGIN_DECLS
GCancellable *cancellable,
GError **error);
+gboolean ostree_sysroot_read_current_subbootversion (OstreeSysroot *self,
+ int bootversion,
+ int *out_subbootversion,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean ostree_sysroot_list_deployments (OstreeSysroot *self,
+ int *out_bootversion,
+ GPtrArray **out_deployments,
+ GCancellable *cancellable,
+ GError **error);
+
+GFile *ostree_sysroot_get_deployment_directory (OstreeSysroot *self,
+ OstreeDeployment *deployment);
+
+GFile * ostree_sysroot_get_deployment_origin_path (GFile *deployment_path);
+
+gboolean ostree_sysroot_cleanup (OstreeSysroot *self,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean ostree_sysroot_get_repo (OstreeSysroot *self,
+ OstreeRepo **out_repo,
+ GCancellable *cancellable,
+ GError **error);
+
+OstreeBootloader *ostree_sysroot_query_bootloader (OstreeSysroot *sysroot);
+
+
G_END_DECLS
if (!g_option_context_parse (context, &argc, &argv, error))
goto out;
- if (!ot_admin_cleanup (ostree_sysroot_get_path (sysroot), cancellable, error))
+ if (!ostree_sysroot_cleanup (sysroot, cancellable, error))
goto out;
ret = TRUE;
refspec = argv[1];
- if (!ot_admin_get_repo (ostree_sysroot_get_path (sysroot), &repo, cancellable, error))
+ if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
goto out;
- if (!ot_admin_list_deployments (ostree_sysroot_get_path (sysroot), ¤t_bootversion, ¤t_deployments,
- cancellable, error))
+ if (!ostree_sysroot_list_deployments (sysroot, ¤t_bootversion, ¤t_deployments,
+ cancellable, error))
{
g_prefix_error (error, "While listing deployments: ");
goto out;
repo_path = g_file_resolve_relative_path (ostree_sysroot_get_path (sysroot), "ostree/repo");
- if (!ot_admin_list_deployments (ostree_sysroot_get_path (sysroot), &bootversion, &deployments,
- cancellable, error))
+ if (!ostree_sysroot_list_deployments (sysroot, &bootversion, &deployments,
+ cancellable, error))
{
g_prefix_error (error, "While listing deployments: ");
goto out;
goto out;
}
- deployment_dir = ot_admin_get_deployment_directory (ostree_sysroot_get_path (sysroot), deployment);
+ deployment_dir = ostree_sysroot_get_deployment_directory (sysroot, deployment);
orig_etc_path = g_file_resolve_relative_path (deployment_dir, "usr/etc");
new_etc_path = g_file_resolve_relative_path (deployment_dir, "etc");
if (!g_option_context_parse (context, &argc, &argv, error))
goto out;
- if (!ot_admin_list_deployments (ostree_sysroot_get_path (sysroot), &bootversion, &deployments,
- cancellable, error))
+ if (!ostree_sysroot_list_deployments (sysroot, &bootversion, &deployments,
+ cancellable, error))
{
g_prefix_error (error, "While listing deployments: ");
goto out;
{
int subbootversion;
- if (!ot_admin_read_current_subbootversion (ostree_sysroot_get_path (sysroot), bootversion,
+ if (!ostree_sysroot_read_current_subbootversion (sysroot, bootversion,
&subbootversion,
cancellable, error))
goto out;
deploy_index_str = argv[1];
deploy_index = atoi (deploy_index_str);
- if (!ot_admin_list_deployments (ostree_sysroot_get_path (sysroot), ¤t_bootversion, ¤t_deployments,
- cancellable, error))
+ if (!ostree_sysroot_list_deployments (sysroot, ¤t_bootversion, ¤t_deployments,
+ cancellable, error))
{
g_prefix_error (error, "While listing deployments: ");
goto out;
g_print ("Deleted deployment %s.%d\n", ostree_deployment_get_csum (target_deployment),
ostree_deployment_get_deployserial (target_deployment));
- if (!ot_admin_cleanup (ostree_sysroot_get_path (sysroot), cancellable, error))
+ if (!ostree_sysroot_cleanup (sysroot, cancellable, error))
{
g_prefix_error (error, "Performing final cleanup: ");
goto out;
if (!g_option_context_parse (context, &argc, &argv, error))
goto out;
- if (!ot_admin_list_deployments (ostree_sysroot_get_path (sysroot), ¤t_bootversion,
- ¤t_deployments,
- cancellable, error))
+ if (!ostree_sysroot_list_deployments (sysroot, ¤t_bootversion,
+ ¤t_deployments,
+ cancellable, error))
{
g_prefix_error (error, "While listing deployments: ");
goto out;
merge_deployment = ot_admin_get_merge_deployment (current_deployments, opt_osname,
booted_deployment);
- deployment_path = ot_admin_get_deployment_directory (ostree_sysroot_get_path (sysroot), merge_deployment);
- deployment_origin_path = ot_admin_get_deployment_origin_path (deployment_path);
+ deployment_path = ostree_sysroot_get_deployment_directory (sysroot, merge_deployment);
+ deployment_origin_path = ostree_sysroot_get_deployment_origin_path (deployment_path);
repo_path = g_file_resolve_relative_path (ostree_sysroot_get_path (sysroot), "ostree/repo");
repo = ostree_repo_new (repo_path);
+++ /dev/null
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
- *
- * Copyright (C) 2012 Colin Walters <walters@verbum.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Colin Walters <walters@verbum.org>
- */
-
-#include "config.h"
-
-#include "ot-admin-functions.h"
-#include "otutil.h"
-#include "ostree.h"
-#include "libgsystem.h"
-
-static gboolean
-list_deployment_dirs_for_os (GFile *osdir,
- GPtrArray *inout_deployments,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- const char *osname = gs_file_get_basename_cached (osdir);
- gs_unref_object GFileEnumerator *dir_enum = NULL;
- gs_unref_object GFile *osdeploy_dir = NULL;
- GError *temp_error = NULL;
-
- osdeploy_dir = g_file_get_child (osdir, "deploy");
-
- dir_enum = g_file_enumerate_children (osdeploy_dir, OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL, &temp_error);
- if (!dir_enum)
- {
- if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
- {
- g_clear_error (&temp_error);
- goto done;
- }
- else
- {
- g_propagate_error (error, temp_error);
- goto out;
- }
- }
-
- while (TRUE)
- {
- const char *name;
- GFileInfo *file_info = NULL;
- GFile *child = NULL;
- gs_unref_object OstreeDeployment *deployment = NULL;
- gs_free char *csum = NULL;
- gint deployserial;
-
- if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
- cancellable, error))
- goto out;
- if (file_info == NULL)
- break;
-
- name = g_file_info_get_name (file_info);
-
- if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
- continue;
-
- if (!ot_admin_parse_deploy_path_name (name, &csum, &deployserial, error))
- goto out;
-
- deployment = ostree_deployment_new (-1, osname, csum, deployserial, NULL, -1);
- g_ptr_array_add (inout_deployments, g_object_ref (deployment));
- }
-
- done:
- ret = TRUE;
- out:
- return ret;
-}
-
-static gboolean
-list_all_deployment_directories (GFile *sysroot,
- GPtrArray **out_deployments,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_object GFileEnumerator *dir_enum = NULL;
- gs_unref_object GFile *deploydir = NULL;
- gs_unref_ptrarray GPtrArray *ret_deployments = NULL;
- GError *temp_error = NULL;
-
- deploydir = g_file_resolve_relative_path (sysroot, "ostree/deploy");
-
- ret_deployments = g_ptr_array_new_with_free_func (g_object_unref);
-
- dir_enum = g_file_enumerate_children (deploydir, OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- cancellable, &temp_error);
- if (!dir_enum)
- {
- if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
- {
- g_clear_error (&temp_error);
- goto done;
- }
- else
- {
- g_propagate_error (error, temp_error);
- goto out;
- }
- }
-
- while (TRUE)
- {
- GFileInfo *file_info = NULL;
- GFile *child = NULL;
-
- if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
- NULL, error))
- goto out;
- if (file_info == NULL)
- break;
-
- if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
- continue;
-
- if (!list_deployment_dirs_for_os (child, ret_deployments, cancellable, error))
- goto out;
- }
-
- done:
- ret = TRUE;
- ot_transfer_out_value (out_deployments, &ret_deployments);
- out:
- return ret;
-}
-
-static gboolean
-parse_bootdir_name (const char *name,
- char **out_osname,
- char **out_csum)
-{
- const char *lastdash;
-
- if (out_osname)
- *out_osname = NULL;
- if (out_csum)
- *out_csum = NULL;
-
- lastdash = strrchr (name, '-');
-
- if (!lastdash)
- return FALSE;
-
- if (!ostree_validate_checksum_string (lastdash + 1, NULL))
- return FALSE;
-
- if (out_osname)
- *out_osname = g_strndup (name, lastdash - name);
- if (out_csum)
- *out_csum = g_strdup (lastdash + 1);
-
- return TRUE;
-}
-
-static gboolean
-list_all_boot_directories (GFile *sysroot,
- GPtrArray **out_bootdirs,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_object GFileEnumerator *dir_enum = NULL;
- gs_unref_object GFile *boot_ostree = NULL;
- gs_unref_ptrarray GPtrArray *ret_bootdirs = NULL;
- GError *temp_error = NULL;
-
- boot_ostree = g_file_resolve_relative_path (sysroot, "boot/ostree");
-
- ret_bootdirs = g_ptr_array_new_with_free_func (g_object_unref);
-
- dir_enum = g_file_enumerate_children (boot_ostree, OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- cancellable, &temp_error);
- if (!dir_enum)
- {
- if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
- {
- g_clear_error (&temp_error);
- goto done;
- }
- else
- {
- g_propagate_error (error, temp_error);
- goto out;
- }
- }
-
- while (TRUE)
- {
- GFileInfo *file_info = NULL;
- GFile *child = NULL;
- const char *name;
-
- if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
- NULL, error))
- goto out;
- if (file_info == NULL)
- break;
-
- if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
- continue;
-
- /* Only look at directories ending in -CHECKSUM; nothing else
- * should be in here, but let's be conservative.
- */
- name = g_file_info_get_name (file_info);
- if (!parse_bootdir_name (name, NULL, NULL))
- continue;
-
- g_ptr_array_add (ret_bootdirs, g_object_ref (child));
- }
-
- done:
- ret = TRUE;
- ot_transfer_out_value (out_bootdirs, &ret_bootdirs);
- out:
- return ret;
-}
-
-static gboolean
-cleanup_other_bootversions (GFile *sysroot,
- int bootversion,
- int subbootversion,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- int cleanup_bootversion;
- int cleanup_subbootversion;
- gs_unref_object GFile *cleanup_boot_dir = NULL;
-
- cleanup_bootversion = bootversion == 0 ? 1 : 0;
- cleanup_subbootversion = subbootversion == 0 ? 1 : 0;
-
- cleanup_boot_dir = ot_gfile_resolve_path_printf (sysroot, "boot/loader.%d", cleanup_bootversion);
- if (!gs_shutil_rm_rf (cleanup_boot_dir, cancellable, error))
- goto out;
- g_clear_object (&cleanup_boot_dir);
-
- cleanup_boot_dir = ot_gfile_resolve_path_printf (sysroot, "ostree/boot.%d", cleanup_bootversion);
- if (!gs_shutil_rm_rf (cleanup_boot_dir, cancellable, error))
- goto out;
- g_clear_object (&cleanup_boot_dir);
-
- cleanup_boot_dir = ot_gfile_resolve_path_printf (sysroot, "ostree/boot.%d.0", cleanup_bootversion);
- if (!gs_shutil_rm_rf (cleanup_boot_dir, cancellable, error))
- goto out;
- g_clear_object (&cleanup_boot_dir);
-
- cleanup_boot_dir = ot_gfile_resolve_path_printf (sysroot, "ostree/boot.%d.1", cleanup_bootversion);
- if (!gs_shutil_rm_rf (cleanup_boot_dir, cancellable, error))
- goto out;
- g_clear_object (&cleanup_boot_dir);
-
- cleanup_boot_dir = ot_gfile_resolve_path_printf (sysroot, "ostree/boot.%d.%d", bootversion,
- cleanup_subbootversion);
- if (!gs_shutil_rm_rf (cleanup_boot_dir, cancellable, error))
- goto out;
- g_clear_object (&cleanup_boot_dir);
-
- ret = TRUE;
- out:
- return ret;
-}
-
-static gboolean
-cleanup_old_deployments (GFile *sysroot,
- GPtrArray *deployments,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- guint32 root_device;
- guint64 root_inode;
- guint i;
- gs_unref_object GFile *active_root = g_file_new_for_path ("/");
- gs_unref_hashtable GHashTable *active_deployment_dirs = NULL;
- gs_unref_hashtable GHashTable *active_boot_checksums = NULL;
- gs_unref_ptrarray GPtrArray *all_deployment_dirs = NULL;
- gs_unref_ptrarray GPtrArray *all_boot_dirs = NULL;
-
- if (!ot_admin_util_get_devino (active_root, &root_device, &root_inode,
- cancellable, error))
- goto out;
-
- active_deployment_dirs = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, NULL, g_object_unref);
- active_boot_checksums = g_hash_table_new_full (g_str_hash, (GEqualFunc)g_str_equal, g_free, NULL);
-
- for (i = 0; i < deployments->len; i++)
- {
- OstreeDeployment *deployment = deployments->pdata[i];
- GFile *deployment_path = ot_admin_get_deployment_directory (sysroot, deployment);
- char *bootcsum = g_strdup (ostree_deployment_get_bootcsum (deployment));
- /* Transfer ownership */
- g_hash_table_insert (active_deployment_dirs, deployment_path, deployment_path);
- g_hash_table_insert (active_boot_checksums, bootcsum, bootcsum);
- }
-
- if (!list_all_deployment_directories (sysroot, &all_deployment_dirs,
- cancellable, error))
- goto out;
-
- for (i = 0; i < all_deployment_dirs->len; i++)
- {
- OstreeDeployment *deployment = all_deployment_dirs->pdata[i];
- gs_unref_object GFile *deployment_path = ot_admin_get_deployment_directory (sysroot, deployment);
- gs_unref_object GFile *origin_path = ot_admin_get_deployment_origin_path (deployment_path);
- if (!g_hash_table_lookup (active_deployment_dirs, deployment_path))
- {
- guint32 device;
- guint64 inode;
-
- if (!ot_admin_util_get_devino (deployment_path, &device, &inode,
- cancellable, error))
- goto out;
-
- /* This shouldn't happen, because higher levels should
- * disallow having the booted deployment not in the active
- * deployment list, but let's be extra safe. */
- if (device == root_device && inode == root_inode)
- continue;
-
- g_print ("ostadmin: Deleting deployment %s\n", gs_file_get_path_cached (deployment_path));
- if (!gs_shutil_rm_rf (deployment_path, cancellable, error))
- goto out;
- if (!gs_shutil_rm_rf (origin_path, cancellable, error))
- goto out;
- }
- }
-
- if (!list_all_boot_directories (sysroot, &all_boot_dirs,
- cancellable, error))
- goto out;
-
- for (i = 0; i < all_boot_dirs->len; i++)
- {
- GFile *bootdir = all_boot_dirs->pdata[i];
- gs_free char *osname = NULL;
- gs_free char *bootcsum = NULL;
-
- if (!parse_bootdir_name (gs_file_get_basename_cached (bootdir),
- &osname, &bootcsum))
- g_assert_not_reached ();
-
- if (g_hash_table_lookup (active_boot_checksums, bootcsum))
- continue;
-
- g_print ("ostadmin: Deleting bootdir %s\n", gs_file_get_path_cached (bootdir));
- if (!gs_shutil_rm_rf (bootdir, cancellable, error))
- goto out;
- }
-
- ret = TRUE;
- out:
- return ret;
-}
-
-static gboolean
-cleanup_ref_prefix (OstreeRepo *repo,
- int bootversion,
- int subbootversion,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_free char *prefix = NULL;
- gs_unref_hashtable GHashTable *refs = NULL;
- GHashTableIter hashiter;
- gpointer hashkey, hashvalue;
-
- prefix = g_strdup_printf ("ostree/%d/%d", bootversion, subbootversion);
-
- if (!ostree_repo_list_refs (repo, prefix, &refs, cancellable, error))
- goto out;
-
- if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
- goto out;
-
- g_hash_table_iter_init (&hashiter, refs);
- while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))
- {
- const char *suffix = hashkey;
- gs_free char *ref = g_strconcat (prefix, "/", suffix, NULL);
- ostree_repo_transaction_set_refspec (repo, ref, NULL);
- }
-
- if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))
- goto out;
-
- ret = TRUE;
- out:
- ostree_repo_abort_transaction (repo, cancellable, NULL);
- return ret;
-}
-
-static gboolean
-generate_deployment_refs_and_prune (GFile *sysroot,
- OstreeRepo *repo,
- int bootversion,
- int subbootversion,
- GPtrArray *deployments,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- int cleanup_bootversion;
- int cleanup_subbootversion;
- guint i;
- gint n_objects_total, n_objects_pruned;
- guint64 freed_space;
-
- cleanup_bootversion = (bootversion == 0) ? 1 : 0;
- cleanup_subbootversion = (subbootversion == 0) ? 1 : 0;
-
- if (!cleanup_ref_prefix (repo, cleanup_bootversion, 0,
- cancellable, error))
- goto out;
-
- if (!cleanup_ref_prefix (repo, cleanup_bootversion, 1,
- cancellable, error))
- goto out;
-
- if (!cleanup_ref_prefix (repo, bootversion, cleanup_subbootversion,
- cancellable, error))
- goto out;
-
- for (i = 0; i < deployments->len; i++)
- {
- OstreeDeployment *deployment = deployments->pdata[i];
- gs_free char *refname = g_strdup_printf ("ostree/%d/%d/%u",
- bootversion, subbootversion,
- i);
-
- if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
- goto out;
-
- ostree_repo_transaction_set_refspec (repo, refname, ostree_deployment_get_csum (deployment));
-
- if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))
- goto out;
- }
-
- if (!ostree_repo_prune (repo, OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY, 0,
- &n_objects_total, &n_objects_pruned, &freed_space,
- cancellable, error))
- goto out;
- if (freed_space > 0)
- {
- char *freed_space_str = g_format_size_full (freed_space, 0);
- g_print ("Freed objects: %s\n", freed_space_str);
- }
-
- ret = TRUE;
- out:
- ostree_repo_abort_transaction (repo, cancellable, NULL);
- return ret;
-}
-
-gboolean
-ot_admin_cleanup (GFile *sysroot,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_ptrarray GPtrArray *deployments = NULL;
- gs_unref_object OstreeRepo *repo = NULL;
- int bootversion;
- int subbootversion;
-
- if (!ot_admin_list_deployments (sysroot, &bootversion, &deployments,
- cancellable, error))
- goto out;
-
- if (!ot_admin_read_current_subbootversion (sysroot, bootversion, &subbootversion,
- cancellable, error))
- goto out;
-
- if (!cleanup_other_bootversions (sysroot, bootversion, subbootversion,
- cancellable, error))
- goto out;
-
- if (!cleanup_old_deployments (sysroot, deployments,
- cancellable, error))
- goto out;
-
- if (deployments->len > 0)
- {
- if (!ot_admin_get_repo (sysroot, &repo, cancellable, error))
- goto out;
-
- if (!generate_deployment_refs_and_prune (sysroot, repo, bootversion,
- subbootversion, deployments,
- cancellable, error))
- goto out;
- }
-
- ret = TRUE;
- out:
- return ret;
-}
#include "ot-admin-functions.h"
#include "ot-admin-deploy.h"
-#include "ot-bootloader-syslinux.h"
#include "otutil.h"
#include "ostree-core.h"
#include "libgsystem.h"
}
static gboolean
-merge_configuration (GFile *sysroot,
+merge_configuration (OstreeSysroot *sysroot_obj,
OstreeDeployment *previous_deployment,
OstreeDeployment *deployment,
GFile *deployment_path,
gs_unref_object GFile *previous_path = NULL;
OstreeBootconfigParser *previous_bootconfig;
- previous_path = ot_admin_get_deployment_directory (sysroot, previous_deployment);
+ previous_path = ostree_sysroot_get_deployment_directory (sysroot_obj, previous_deployment);
source_etc_path = g_file_resolve_relative_path (previous_path, "etc");
source_etc_pristine_path = g_file_resolve_relative_path (previous_path, "usr/etc");
* them later.
*/
ostree_bootconfig_parser_set (ostree_deployment_get_bootconfig (deployment), "options",
- previous_options);
+ previous_options);
}
}
GError **error)
{
gboolean ret = FALSE;
+ gs_unref_object OstreeSysroot *sysroot_obj = NULL;
GKeyFile *origin = ostree_deployment_get_origin (deployment);
+ sysroot_obj = ostree_sysroot_new (sysroot);
+
if (origin)
{
- gs_unref_object GFile *deployment_path = ot_admin_get_deployment_directory (sysroot, deployment);
- gs_unref_object GFile *origin_path = ot_admin_get_deployment_origin_path (deployment_path);
+ gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (sysroot_obj, deployment);
+ gs_unref_object GFile *origin_path = ostree_sysroot_get_deployment_origin_path (deployment_path);
gs_free char *contents = NULL;
gsize len;
}
static gboolean
-swap_bootlinks (GFile *sysroot,
+swap_bootlinks (OstreeSysroot *sysroot,
int current_bootversion,
GPtrArray *new_deployments,
GCancellable *cancellable,
gboolean ret = FALSE;
guint i;
int old_subbootversion, new_subbootversion;
- gs_unref_object GFile *ostree_dir = g_file_get_child (sysroot, "ostree");
+ gs_unref_object GFile *ostree_dir = g_file_get_child (ostree_sysroot_get_path (sysroot), "ostree");
gs_free char *ostree_bootdir_name = g_strdup_printf ("boot.%d", current_bootversion);
gs_unref_object GFile *ostree_bootdir = g_file_resolve_relative_path (ostree_dir, ostree_bootdir_name);
gs_free char *ostree_subbootdir_name = NULL;
gs_unref_object GFile *ostree_subbootdir = NULL;
- if (!ot_admin_read_current_subbootversion (sysroot, current_bootversion,
- &old_subbootversion,
- cancellable, error))
+ if (!ostree_sysroot_read_current_subbootversion (sysroot, current_bootversion,
+ &old_subbootversion,
+ cancellable, error))
goto out;
new_subbootversion = old_subbootversion == 0 ? 1 : 0;
* Write out an entry in /boot/loader/entries for @deployment.
*/
static gboolean
-install_deployment_kernel (GFile *sysroot,
+install_deployment_kernel (OstreeSysroot *sysroot,
int new_bootversion,
OstreeDeployment *deployment,
guint n_deployments,
gsize len;
bootconfig = ostree_deployment_get_bootconfig (deployment);
- deployment_dir = ot_admin_get_deployment_directory (sysroot, deployment);
+ deployment_dir = ostree_sysroot_get_deployment_directory (sysroot, deployment);
if (!get_kernel_from_tree (deployment_dir, &tree_kernel_path, &tree_initramfs_path,
cancellable, error))
goto out;
- bootdir = g_file_get_child (sysroot, "boot");
+ bootdir = g_file_get_child (ostree_sysroot_get_path (sysroot), "boot");
bootcsumdir = ot_gfile_resolve_path_printf (bootdir, "ostree/%s-%s",
osname,
bootcsum);
{
gboolean ret = FALSE;
guint i;
- gs_unref_object OtBootloader *bootloader = ot_admin_query_bootloader (sysroot);
+ gs_unref_object OstreeSysroot *sysroot_obj = ostree_sysroot_new (sysroot);
+ gs_unref_object OstreeBootloader *bootloader = ostree_sysroot_query_bootloader (sysroot_obj);
if (bootloader)
- g_print ("Detected bootloader: %s\n", ot_bootloader_get_name (bootloader));
+ g_print ("Detected bootloader: %s\n", ostree_bootloader_get_name (bootloader));
else
g_print ("Detected bootloader: (unknown)\n");
goto out;
}
- if (!swap_bootlinks (sysroot, current_bootversion,
+ if (!swap_bootlinks (sysroot_obj, current_bootversion,
new_deployments,
cancellable, error))
{
for (i = 0; i < new_deployments->len; i++)
{
OstreeDeployment *deployment = new_deployments->pdata[i];
- if (!install_deployment_kernel (sysroot, new_bootversion,
+ if (!install_deployment_kernel (sysroot_obj, new_bootversion,
deployment, new_deployments->len,
cancellable, error))
{
}
/* Swap bootlinks for *new* version */
- if (!swap_bootlinks (sysroot, new_bootversion, new_deployments,
+ if (!swap_bootlinks (sysroot_obj, new_bootversion, new_deployments,
cancellable, error))
{
g_prefix_error (error, "Generating new bootlinks: ");
goto out;
}
- if (bootloader && !ot_bootloader_write_config (bootloader, new_bootversion,
- cancellable, error))
+ if (bootloader && !ostree_bootloader_write_config (bootloader, new_bootversion,
+ cancellable, error))
{
g_prefix_error (error, "Bootloader write config: ");
goto out;
{
gboolean ret = FALSE;
OstreeDeployment *new_deployment;
+ gs_unref_object OstreeSysroot *sysroot_obj = NULL;
gs_unref_object OstreeDeployment *merge_deployment = NULL;
gs_unref_object OstreeRepo *repo = NULL;
gs_unref_object GFile *commit_root = NULL;
gs_unref_ptrarray GPtrArray *new_deployments = NULL;
int new_bootversion;
- if (!ot_admin_get_repo (sysroot, &repo, cancellable, error))
+ sysroot_obj = ostree_sysroot_new (sysroot);
+
+ if (!ostree_sysroot_get_repo (sysroot_obj, &repo, cancellable, error))
goto out;
/* Here we perform cleanup of any leftover data from previous
* TODO: Add /ostree/transaction file, and only do this cleanup if
* we find it.
*/
- if (!ot_admin_cleanup (sysroot, cancellable, error))
+ if (!ostree_sysroot_cleanup (sysroot_obj, cancellable, error))
{
g_prefix_error (error, "Performing initial cleanup: ");
goto out;
bootconfig = ostree_bootconfig_parser_new ();
ostree_deployment_set_bootconfig (new_deployment, bootconfig);
- if (!merge_configuration (sysroot, merge_deployment, new_deployment,
+ if (!merge_configuration (sysroot_obj, merge_deployment, new_deployment,
new_deployment_path,
cancellable, error))
{
/* And finally, cleanup of any leftover data.
*/
- if (!ot_admin_cleanup (sysroot, cancellable, error))
+ if (!ostree_sysroot_cleanup (sysroot_obj, cancellable, error))
{
g_prefix_error (error, "Performing final cleanup: ");
goto out;
#include <gio/gio.h>
#include <ostree.h>
-#include "ot-bootloader.h"
#include "ot-ordered-hash.h"
G_BEGIN_DECLS
#include "config.h"
#include "ot-admin-functions.h"
-#include "ot-bootloader-syslinux.h"
-#include "ot-bootloader-uboot.h"
#include "otutil.h"
#include "ostree.h"
#include "libgsystem.h"
return g_string_free (buf, FALSE);
}
-
-static void
-match_info_cleanup (void *loc)
-{
- GMatchInfo **match = (GMatchInfo**)loc;
- if (*match) g_match_info_unref (*match);
-}
-
gboolean
ot_admin_check_os (GFile *sysroot,
const char *osname,
return ret;
}
-static gboolean
-parse_bootlink (const char *bootlink,
- int *out_entry_bootversion,
- char **out_osname,
- char **out_bootcsum,
- int *out_treebootserial,
- GError **error)
-{
- gboolean ret = FALSE;
- __attribute__((cleanup(match_info_cleanup))) GMatchInfo *match = NULL;
- gs_free char *bootversion_str = NULL;
- gs_free char *treebootserial_str = NULL;
-
- static gsize regex_initialized;
- static GRegex *regex;
-
- if (g_once_init_enter (®ex_initialized))
- {
- regex = g_regex_new ("^/ostree/boot.([01])/([^/]+)/([^/]+)/([0-9]+)$", 0, 0, NULL);
- g_assert (regex);
- g_once_init_leave (®ex_initialized, 1);
- }
-
- if (!g_regex_match (regex, bootlink, 0, &match))
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Invalid ostree= argument '%s', expected ostree=/ostree/boot.BOOTVERSION/OSNAME/BOOTCSUM/TREESERIAL", bootlink);
- goto out;
- }
-
- bootversion_str = g_match_info_fetch (match, 1);
- *out_entry_bootversion = (int)g_ascii_strtoll (bootversion_str, NULL, 10);
- *out_osname = g_match_info_fetch (match, 2);
- *out_bootcsum = g_match_info_fetch (match, 3);
- treebootserial_str = g_match_info_fetch (match, 4);
- *out_treebootserial = (int)g_ascii_strtoll (treebootserial_str, NULL, 10);
-
- ret = TRUE;
- out:
- return ret;
-}
-
-gboolean
-ot_admin_parse_deploy_path_name (const char *name,
- char **out_csum,
- int *out_serial,
- GError **error)
-{
- gboolean ret = FALSE;
- __attribute__((cleanup(match_info_cleanup))) GMatchInfo *match = NULL;
- gs_free char *serial_str = NULL;
-
- static gsize regex_initialized;
- static GRegex *regex;
-
- if (g_once_init_enter (®ex_initialized))
- {
- regex = g_regex_new ("^([0-9a-f]+)\\.([0-9]+)$", 0, 0, NULL);
- g_assert (regex);
- g_once_init_leave (®ex_initialized, 1);
- }
-
- if (!g_regex_match (regex, name, 0, &match))
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Invalid deploy name '%s', expected CHECKSUM.TREESERIAL", name);
- goto out;
- }
-
- *out_csum = g_match_info_fetch (match, 1);
- serial_str = g_match_info_fetch (match, 2);
- *out_serial = (int)g_ascii_strtoll (serial_str, NULL, 10);
-
- ret = TRUE;
- out:
- return ret;
-}
-
-GFile *
-ot_admin_get_deployment_origin_path (GFile *deployment_path)
-{
- gs_unref_object GFile *deployment_parent = g_file_get_parent (deployment_path);
- return ot_gfile_resolve_path_printf (deployment_parent,
- "%s.origin",
- gs_file_get_path_cached (deployment_path));
-}
-
-static gboolean
-parse_origin (GFile *sysroot,
- GFile *deployment_path,
- GKeyFile **out_origin,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- GKeyFile *ret_origin = NULL;
- gs_unref_object GFile *origin_path = ot_admin_get_deployment_origin_path (deployment_path);
- gs_free char *origin_contents = NULL;
-
- if (!ot_gfile_load_contents_utf8_allow_noent (origin_path, &origin_contents,
- cancellable, error))
- goto out;
-
- if (origin_contents)
- {
- ret_origin = g_key_file_new ();
- if (!g_key_file_load_from_data (ret_origin, origin_contents, -1, 0, error))
- goto out;
- }
-
- ret = TRUE;
- ot_transfer_out_value (out_origin, &ret_origin);
- out:
- if (error)
- g_prefix_error (error, "Parsing %s: ", gs_file_get_path_cached (origin_path));
- if (ret_origin)
- g_key_file_unref (ret_origin);
- return ret;
-}
-
-static gboolean
-parse_deployment (GFile *sysroot,
- const char *boot_link,
- OstreeDeployment **out_deployment,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- const char *relative_boot_link;
- gs_unref_object OstreeDeployment *ret_deployment = NULL;
- int entry_boot_version;
- int treebootserial = -1;
- int deployserial = -1;
- gs_free char *osname = NULL;
- gs_free char *bootcsum = NULL;
- gs_free char *treecsum = NULL;
- gs_unref_object GFile *treebootserial_link = NULL;
- gs_unref_object GFileInfo *treebootserial_info = NULL;
- gs_unref_object GFile *treebootserial_target = NULL;
- GKeyFile *origin = NULL;
-
- if (!parse_bootlink (boot_link, &entry_boot_version,
- &osname, &bootcsum, &treebootserial,
- error))
- goto out;
-
- relative_boot_link = boot_link;
- if (*relative_boot_link == '/')
- relative_boot_link++;
- treebootserial_link = g_file_resolve_relative_path (sysroot, relative_boot_link);
- treebootserial_info = g_file_query_info (treebootserial_link, OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- cancellable, error);
- if (!treebootserial_info)
- goto out;
-
- if (!ot_gfile_get_symlink_target_from_info (treebootserial_link, treebootserial_info,
- &treebootserial_target, cancellable, error))
- goto out;
-
- if (!ot_admin_parse_deploy_path_name (gs_file_get_basename_cached (treebootserial_target),
- &treecsum, &deployserial, error))
- goto out;
-
- if (!parse_origin (sysroot, treebootserial_target, &origin,
- cancellable, error))
- goto out;
-
- ret_deployment = ostree_deployment_new (-1, osname, treecsum, deployserial,
- bootcsum, treebootserial);
- if (origin)
- ostree_deployment_set_origin (ret_deployment, origin);
-
- ret = TRUE;
- ot_transfer_out_value (out_deployment, &ret_deployment);
- out:
- if (origin)
- g_key_file_unref (origin);
- return ret;
-}
-
static gboolean
parse_kernel_commandline (OtOrderedHash **out_args,
GCancellable *cancellable,
{
gboolean ret = FALSE;
gs_unref_object GFile *active_root = g_file_new_for_path ("/");
+ gs_unref_object OstreeSysroot *active_deployment_root = ostree_sysroot_new_default ();
gs_unref_object OstreeDeployment *ret_deployment = NULL;
if (g_file_equal (active_root, target_sysroot))
for (i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];
- gs_unref_object GFile *deployment_path = ot_admin_get_deployment_directory (active_root, deployment);
+ gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (active_deployment_root, deployment);
guint32 device;
guint64 inode;
return NULL;
}
-static gboolean
-read_current_bootversion (GFile *sysroot,
- int *out_bootversion,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_object GFile *boot_loader_path = g_file_resolve_relative_path (sysroot, "boot/loader");
- gs_unref_object GFileInfo *info = NULL;
- const char *target;
- int ret_bootversion;
-
- if (!ot_gfile_query_info_allow_noent (boot_loader_path, OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- &info,
- cancellable, error))
- goto out;
-
- if (info == NULL)
- ret_bootversion = 0;
- else
- {
- if (g_file_info_get_file_type (info) != G_FILE_TYPE_SYMBOLIC_LINK)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Not a symbolic link: %s", gs_file_get_path_cached (boot_loader_path));
- goto out;
- }
-
- target = g_file_info_get_symlink_target (info);
- if (g_strcmp0 (target, "loader.0") == 0)
- ret_bootversion = 0;
- else if (g_strcmp0 (target, "loader.1") == 0)
- ret_bootversion = 1;
- else
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Invalid target '%s' in %s", target, gs_file_get_path_cached (boot_loader_path));
- goto out;
- }
- }
-
- ret = TRUE;
- *out_bootversion = ret_bootversion;
- out:
- return ret;
-}
-
-gboolean
-ot_admin_read_current_subbootversion (GFile *sysroot,
- int bootversion,
- int *out_subbootversion,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_object GFile *ostree_dir = g_file_get_child (sysroot, "ostree");
- gs_free char *ostree_bootdir_name = g_strdup_printf ("boot.%d", bootversion);
- gs_unref_object GFile *ostree_bootdir = g_file_resolve_relative_path (ostree_dir, ostree_bootdir_name);
- gs_unref_object GFile *ostree_subbootdir = NULL;
-
- if (!ot_gfile_query_symlink_target_allow_noent (ostree_bootdir, &ostree_subbootdir,
- cancellable, error))
- goto out;
-
- if (ostree_subbootdir == NULL)
- {
- *out_subbootversion = 0;
- }
- else
- {
- const char *current_subbootdir_name = gs_file_get_basename_cached (ostree_subbootdir);
- if (g_str_has_suffix (current_subbootdir_name, ".0"))
- *out_subbootversion = 0;
- else if (g_str_has_suffix (current_subbootdir_name, ".1"))
- *out_subbootversion = 1;
- else
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Invalid target '%s' in %s",
- gs_file_get_path_cached (ostree_subbootdir),
- gs_file_get_path_cached (ostree_bootdir));
- goto out;
- }
- }
-
- ret = TRUE;
- out:
- return ret;
-}
-
-gboolean
-ot_admin_read_boot_loader_configs (GFile *sysroot,
- int bootversion,
- GPtrArray **out_loader_configs,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_object GFileEnumerator *dir_enum = NULL;
- gs_unref_object GFile *loader_entries_dir = NULL;
- gs_unref_ptrarray GPtrArray *ret_loader_configs = NULL;
- GError *temp_error = NULL;
-
- loader_entries_dir = ot_gfile_resolve_path_printf (sysroot, "boot/loader.%d/entries",
- bootversion);
- ret_loader_configs = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
-
- dir_enum = g_file_enumerate_children (loader_entries_dir, OSTREE_GIO_FAST_QUERYINFO,
- 0, NULL, &temp_error);
- if (!dir_enum)
- {
- if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
- {
- g_clear_error (&temp_error);
- goto done;
- }
- else
- {
- g_propagate_error (error, temp_error);
- goto out;
- }
- }
-
- while (TRUE)
- {
- GFileInfo *file_info;
- GFile *child;
- const char *name;
-
- if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
- cancellable, error))
- goto out;
- if (file_info == NULL)
- break;
-
- name = g_file_info_get_name (file_info);
-
- if (g_str_has_prefix (name, "ostree-") &&
- g_str_has_suffix (name, ".conf") &&
- g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
- {
- gs_unref_object OstreeBootconfigParser *config = ostree_bootconfig_parser_new ();
-
- if (!ostree_bootconfig_parser_parse (config, child, cancellable, error))
- {
- g_prefix_error (error, "Parsing %s: ", gs_file_get_path_cached (child));
- goto out;
- }
-
- g_ptr_array_add (ret_loader_configs, g_object_ref (config));
- }
- }
-
- done:
- ot_transfer_out_value (out_loader_configs, &ret_loader_configs);
- ret = TRUE;
- out:
- return ret;
-}
-
-static char *
-get_ostree_kernel_arg_from_config (OstreeBootconfigParser *config)
-{
- const char *options;
- char *ret = NULL;
- char **opts, **iter;
-
- options = ostree_bootconfig_parser_get (config, "options");
- if (!options)
- return NULL;
-
- opts = g_strsplit (options, " ", -1);
- for (iter = opts; *iter; iter++)
- {
- const char *opt = *iter;
- if (g_str_has_prefix (opt, "ostree="))
- {
- ret = g_strdup (opt + strlen ("ostree="));
- break;
- }
- }
- g_strfreev (opts);
-
- return ret;
-}
-
-static gboolean
-list_deployments_process_one_boot_entry (GFile *sysroot,
- OstreeBootconfigParser *config,
- GPtrArray *inout_deployments,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_free char *ostree_arg = NULL;
- gs_unref_object OstreeDeployment *deployment = NULL;
-
- ostree_arg = get_ostree_kernel_arg_from_config (config);
- if (ostree_arg == NULL)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "No ostree= kernel argument found");
- goto out;
- }
-
- if (!parse_deployment (sysroot, ostree_arg, &deployment,
- cancellable, error))
- goto out;
-
- ostree_deployment_set_bootconfig (deployment, config);
-
- g_ptr_array_add (inout_deployments, g_object_ref (deployment));
-
- ret = TRUE;
- out:
- return ret;
-}
-
-static gint
-compare_deployments_by_boot_loader_version_reversed (gconstpointer a_pp,
- gconstpointer b_pp)
-{
- OstreeDeployment *a = *((OstreeDeployment**)a_pp);
- OstreeDeployment *b = *((OstreeDeployment**)b_pp);
- OstreeBootconfigParser *a_bootconfig = ostree_deployment_get_bootconfig (a);
- OstreeBootconfigParser *b_bootconfig = ostree_deployment_get_bootconfig (b);
- const char *a_version = ostree_bootconfig_parser_get (a_bootconfig, "version");
- const char *b_version = ostree_bootconfig_parser_get (b_bootconfig, "version");
-
- if (a_version && b_version)
- {
- int r = strverscmp (a_version, b_version);
- /* Reverse */
- return -r;
- }
- else if (a_version)
- return -1;
- else
- return 1;
-}
-
-gboolean
-ot_admin_list_deployments (GFile *sysroot,
- int *out_current_bootversion,
- GPtrArray **out_deployments,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_ptrarray GPtrArray *boot_loader_configs = NULL;
- gs_unref_ptrarray GPtrArray *ret_deployments = NULL;
- guint i;
- int bootversion = -1;
-
- if (!read_current_bootversion (sysroot, &bootversion, cancellable, error))
- goto out;
-
- if (!ot_admin_read_boot_loader_configs (sysroot, bootversion, &boot_loader_configs,
- cancellable, error))
- goto out;
-
- ret_deployments = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
-
- for (i = 0; i < boot_loader_configs->len; i++)
- {
- OstreeBootconfigParser *config = boot_loader_configs->pdata[i];
-
- if (!list_deployments_process_one_boot_entry (sysroot, config, ret_deployments,
- cancellable, error))
- goto out;
- }
-
- g_ptr_array_sort (ret_deployments, compare_deployments_by_boot_loader_version_reversed);
- for (i = 0; i < ret_deployments->len; i++)
- {
- OstreeDeployment *deployment = ret_deployments->pdata[i];
- ostree_deployment_set_index (deployment, i);
- }
-
- ret = TRUE;
- *out_current_bootversion = bootversion;
- ot_transfer_out_value (out_deployments, &ret_deployments);
- out:
- return ret;
-}
-
-GFile *
-ot_admin_get_deployment_directory (GFile *sysroot,
- OstreeDeployment *deployment)
-{
- gs_free char *path = g_strdup_printf ("ostree/deploy/%s/deploy/%s.%d",
- ostree_deployment_get_osname (deployment),
- ostree_deployment_get_csum (deployment),
- ostree_deployment_get_deployserial (deployment));
- return g_file_resolve_relative_path (sysroot, path);
-}
-
-OtBootloader *
-ot_admin_query_bootloader (GFile *sysroot)
-{
- OtBootloaderSyslinux *syslinux;
- OtBootloaderUboot *uboot;
-
- syslinux = ot_bootloader_syslinux_new (sysroot);
- if (ot_bootloader_query ((OtBootloader*)syslinux))
- return (OtBootloader*) (syslinux);
-
- uboot = ot_bootloader_uboot_new (sysroot);
- if (ot_bootloader_query ((OtBootloader*)uboot))
- return (OtBootloader*) (uboot);
-
- return NULL;
-}
-
GKeyFile *
ot_origin_new_from_refspec (const char *refspec)
{
g_key_file_set_string (ret, "origin", "refspec", refspec);
return ret;
}
-
-gboolean
-ot_admin_get_repo (GFile *sysroot,
- OstreeRepo **out_repo,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_object OstreeRepo *ret_repo = NULL;
- gs_unref_object GFile *repo_path = g_file_resolve_relative_path (sysroot, "ostree/repo");
-
- ret_repo = ostree_repo_new (repo_path);
- if (!ostree_repo_open (ret_repo, cancellable, error))
- goto out;
-
- ret = TRUE;
- ot_transfer_out_value (out_repo, &ret_repo);
- out:
- return ret;
-}
#include <gio/gio.h>
#include <ostree.h>
-#include "ot-bootloader.h"
#include "ot-ordered-hash.h"
G_BEGIN_DECLS
GCancellable *cancellable,
GError **error);
-char *ot_admin_join_lines (GPtrArray *lines);
-
-gboolean ot_admin_parse_deploy_path_name (const char *name,
- char **out_csum,
- int *out_serial,
- GError **error);
-
gboolean ot_admin_ensure_initialized (GFile *ostree_dir,
GCancellable *cancellable,
GError **error);
OtOrderedHash *ot_admin_parse_kernel_args (const char *options);
char * ot_admin_kernel_arg_string_serialize (OtOrderedHash *ohash);
-OtBootloader *ot_admin_query_bootloader (GFile *sysroot);
-
-gboolean ot_admin_read_current_subbootversion (GFile *sysroot,
- int bootversion,
- int *out_subbootversion,
- GCancellable *cancellable,
- GError **error);
-
-gboolean ot_admin_read_boot_loader_configs (GFile *boot_dir,
- int bootversion,
- GPtrArray **out_loader_configs,
- GCancellable *cancellable,
- GError **error);
-
-gboolean ot_admin_list_deployments (GFile *sysroot,
- int *out_bootversion,
- GPtrArray **out_deployments,
- GCancellable *cancellable,
- GError **error);
-
gboolean ot_admin_find_booted_deployment (GFile *sysroot,
GPtrArray *deployments,
OstreeDeployment **out_deployment,
const char *osname,
OstreeDeployment *booted_deployment);
-GFile *ot_admin_get_deployment_origin_path (GFile *deployment_path);
-
-GFile *ot_admin_get_deployment_directory (GFile *sysroot,
- OstreeDeployment *deployment);
-
-gboolean ot_admin_get_repo (GFile *sysroot,
- OstreeRepo **out_repo,
- GCancellable *cancellable,
- GError **error);
-
-gboolean ot_admin_cleanup (GFile *sysroot,
- GCancellable *cancellable,
- GError **error);
-
gboolean ot_admin_get_default_ostree_dir (GFile **out_ostree_dir,
GCancellable *cancellable,
GError **error);
return ret;
}
-char *
-ot_admin_join_lines (GPtrArray *lines)
-{
- GString *buf = g_string_new ("");
- guint i;
- gboolean prev_was_empty = FALSE;
-
- for (i = 0; i < lines->len; i++)
- {
- const char *line = lines->pdata[i];
- /* Special bit to remove extraneous empty lines */
- if (*line == '\0')
- {
- if (prev_was_empty || i == 0)
- continue;
- else
- prev_was_empty = TRUE;
- }
- g_string_append (buf, line);
- g_string_append_c (buf, '\n');
- }
- return g_string_free (buf, FALSE);
-}
+++ /dev/null
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
- *
- * Copyright (C) 2013 Colin Walters <walters@verbum.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the licence or (at
- * your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include "ot-bootloader-syslinux.h"
-#include "otutil.h"
-#include "ot-admin-functions.h"
-#include "libgsystem.h"
-
-#include <string.h>
-
-struct _OtBootloaderSyslinux
-{
- GObject parent_instance;
-
- GFile *sysroot;
- GFile *config_path;
-};
-
-typedef GObjectClass OtBootloaderSyslinuxClass;
-
-static void ot_bootloader_syslinux_bootloader_iface_init (OtBootloaderInterface *iface);
-G_DEFINE_TYPE_WITH_CODE (OtBootloaderSyslinux, ot_bootloader_syslinux, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (OT_TYPE_BOOTLOADER, ot_bootloader_syslinux_bootloader_iface_init));
-
-static gboolean
-ot_bootloader_syslinux_query (OtBootloader *bootloader)
-{
- OtBootloaderSyslinux *self = OT_BOOTLOADER_SYSLINUX (bootloader);
-
- return g_file_query_file_type (self->config_path, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL) == G_FILE_TYPE_SYMBOLIC_LINK;
-}
-
-static const char *
-ot_bootloader_syslinux_get_name (OtBootloader *bootloader)
-{
- return "syslinux";
-}
-
-static gboolean
-append_config_from_boot_loader_entries (OtBootloaderSyslinux *self,
- gboolean regenerate_default,
- int bootversion,
- GPtrArray *new_lines,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_ptrarray GPtrArray *boot_loader_configs = NULL;
- guint i;
-
- if (!ot_admin_read_boot_loader_configs (self->sysroot, bootversion, &boot_loader_configs,
- cancellable, error))
- goto out;
-
- for (i = 0; i < boot_loader_configs->len; i++)
- {
- OstreeBootconfigParser *config = boot_loader_configs->pdata[i];
- const char *val;
-
- val = ostree_bootconfig_parser_get (config, "title");
- if (!val)
- val = "(Untitled)";
-
- if (regenerate_default && i == 0)
- {
- g_ptr_array_add (new_lines, g_strdup_printf ("DEFAULT %s", val));
- }
-
- g_ptr_array_add (new_lines, g_strdup_printf ("LABEL %s", val));
-
- val = ostree_bootconfig_parser_get (config, "linux");
- if (!val)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "No \"linux\" key in bootloader config");
- goto out;
- }
- g_ptr_array_add (new_lines, g_strdup_printf ("\tKERNEL %s", val));
-
- val = ostree_bootconfig_parser_get (config, "initrd");
- if (val)
- g_ptr_array_add (new_lines, g_strdup_printf ("\tINITRD %s", val));
-
- val = ostree_bootconfig_parser_get (config, "options");
- if (val)
- g_ptr_array_add (new_lines, g_strdup_printf ("\tAPPEND %s", val));
- }
-
- ret = TRUE;
- out:
- return ret;
-}
-
-static gboolean
-ot_bootloader_syslinux_write_config (OtBootloader *bootloader,
- int bootversion,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- OtBootloaderSyslinux *self = OT_BOOTLOADER_SYSLINUX (bootloader);
- gs_unref_object GFile *new_config_path = NULL;
- gs_free char *config_contents = NULL;
- gs_free char *new_config_contents = NULL;
- gs_unref_ptrarray GPtrArray *new_lines = NULL;
- gs_unref_ptrarray GPtrArray *tmp_lines = NULL;
- gs_free char *kernel_arg = NULL;
- gboolean saw_default = FALSE;
- gboolean regenerate_default = FALSE;
- gboolean parsing_label = FALSE;
- char **lines = NULL;
- char **iter;
- guint i;
-
- new_config_path = ot_gfile_resolve_path_printf (self->sysroot, "boot/loader.%d/syslinux.cfg",
- bootversion);
-
- /* This should follow the symbolic link to the current bootversion. */
- config_contents = gs_file_load_contents_utf8 (self->config_path, cancellable, error);
- if (!config_contents)
- goto out;
-
- lines = g_strsplit (config_contents, "\n", -1);
- new_lines = g_ptr_array_new_with_free_func (g_free);
- tmp_lines = g_ptr_array_new_with_free_func (g_free);
-
- /* Note special iteration condition here; we want to also loop one
- * more time at the end where line = NULL to ensure we finish off
- * processing the last LABEL.
- */
- iter = lines;
- while (TRUE)
- {
- char *line = *iter;
- gboolean skip = FALSE;
-
- if (parsing_label &&
- (line == NULL || !g_str_has_prefix (line, "\t")))
- {
- parsing_label = FALSE;
- if (kernel_arg == NULL)
- {
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "No KERNEL argument found after LABEL");
- goto out;
- }
-
- /* If this is a non-ostree kernel, just emit the lines
- * we saw.
- */
- if (!g_str_has_prefix (kernel_arg, "/ostree/"))
- {
- for (i = 0; i < tmp_lines->len; i++)
- {
- g_ptr_array_add (new_lines, tmp_lines->pdata[i]);
- tmp_lines->pdata[i] = NULL; /* Transfer ownership */
- }
- }
- else
- {
- /* Otherwise, we drop the config on the floor - it
- * will be regenerated.
- */
- g_ptr_array_set_size (tmp_lines, 0);
- }
- }
-
- if (line == NULL)
- break;
-
- if (!parsing_label &&
- (g_str_has_prefix (line, "LABEL ")))
- {
- parsing_label = TRUE;
- g_ptr_array_set_size (tmp_lines, 0);
- }
- else if (parsing_label && g_str_has_prefix (line, "\tKERNEL "))
- {
- g_free (kernel_arg);
- kernel_arg = g_strdup (line + strlen ("\tKERNEL "));
- }
- else if (!parsing_label &&
- (g_str_has_prefix (line, "DEFAULT ")))
- {
- saw_default = TRUE;
- if (g_str_has_prefix (line, "DEFAULT ostree:"))
- regenerate_default = TRUE;
- skip = TRUE;
- }
-
- if (skip)
- {
- g_free (line);
- }
- else
- {
- if (parsing_label)
- {
- g_ptr_array_add (tmp_lines, line);
- }
- else
- {
- g_ptr_array_add (new_lines, line);
- }
- }
- /* Transfer ownership */
- *iter = NULL;
- iter++;
- }
-
- if (!saw_default)
- regenerate_default = TRUE;
-
- if (!append_config_from_boot_loader_entries (self, regenerate_default,
- bootversion, new_lines,
- cancellable, error))
- goto out;
-
- new_config_contents = ot_admin_join_lines (new_lines);
-
- if (strcmp (new_config_contents, config_contents) != 0)
- {
- if (!g_file_replace_contents (new_config_path, new_config_contents,
- strlen (new_config_contents),
- NULL, FALSE, G_FILE_CREATE_NONE,
- NULL, cancellable, error))
- goto out;
- g_print ("Saved new version of %s\n", gs_file_get_path_cached (self->config_path));
- }
-
- ret = TRUE;
- out:
- g_free (lines); /* Note we freed elements individually */
- return ret;
-}
-
-static void
-ot_bootloader_syslinux_finalize (GObject *object)
-{
- OtBootloaderSyslinux *self = OT_BOOTLOADER_SYSLINUX (object);
-
- g_clear_object (&self->sysroot);
- g_clear_object (&self->config_path);
-
- G_OBJECT_CLASS (ot_bootloader_syslinux_parent_class)->finalize (object);
-}
-
-void
-ot_bootloader_syslinux_init (OtBootloaderSyslinux *self)
-{
-}
-
-static void
-ot_bootloader_syslinux_bootloader_iface_init (OtBootloaderInterface *iface)
-{
- iface->query = ot_bootloader_syslinux_query;
- iface->get_name = ot_bootloader_syslinux_get_name;
- iface->write_config = ot_bootloader_syslinux_write_config;
-}
-
-void
-ot_bootloader_syslinux_class_init (OtBootloaderSyslinuxClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
-
- object_class->finalize = ot_bootloader_syslinux_finalize;
-}
-
-OtBootloaderSyslinux *
-ot_bootloader_syslinux_new (GFile *sysroot)
-{
- OtBootloaderSyslinux *self = g_object_new (OT_TYPE_BOOTLOADER_SYSLINUX, NULL);
- self->sysroot = g_object_ref (sysroot);
- self->config_path = g_file_resolve_relative_path (self->sysroot, "boot/syslinux/syslinux.cfg");
- return self;
-}
+++ /dev/null
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
- *
- * Copyright (C) 2013 Colin Walters <walters@verbum.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the licence or (at
- * your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#pragma once
-
-#include "ot-bootloader.h"
-
-G_BEGIN_DECLS
-
-#define OT_TYPE_BOOTLOADER_SYSLINUX (ot_bootloader_syslinux_get_type ())
-#define OT_BOOTLOADER_SYSLINUX(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), OT_TYPE_BOOTLOADER_SYSLINUX, OtBootloaderSyslinux))
-#define OT_IS_BOOTLOADER_SYSLINUX(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), OT_TYPE_BOOTLOADER_SYSLINUX))
-
-typedef struct _OtBootloaderSyslinux OtBootloaderSyslinux;
-
-GType ot_bootloader_syslinux_get_type (void) G_GNUC_CONST;
-
-OtBootloaderSyslinux * ot_bootloader_syslinux_new (GFile *sysroot);
-
-G_END_DECLS
-
+++ /dev/null
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
- *
- * Copyright (C) 2013 Collabora Ltd
- *
- * Based on ot-bootloader-syslinux.c by Colin Walters <walters@verbum.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the licence or (at
- * your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
- */
-
-#include "config.h"
-
-#include "ot-bootloader-uboot.h"
-#include "otutil.h"
-#include "ot-admin-functions.h"
-#include "libgsystem.h"
-
-#include <string.h>
-
-struct _OtBootloaderUboot
-{
- GObject parent_instance;
-
- GFile *sysroot;
- GFile *config_path;
-};
-
-typedef GObjectClass OtBootloaderUbootClass;
-
-static void ot_bootloader_uboot_bootloader_iface_init (OtBootloaderInterface *iface);
-G_DEFINE_TYPE_WITH_CODE (OtBootloaderUboot, ot_bootloader_uboot, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (OT_TYPE_BOOTLOADER, ot_bootloader_uboot_bootloader_iface_init));
-
-static gboolean
-ot_bootloader_uboot_query (OtBootloader *bootloader)
-{
- OtBootloaderUboot *self = OT_BOOTLOADER_UBOOT (bootloader);
-
- return g_file_query_file_type (self->config_path, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL) == G_FILE_TYPE_SYMBOLIC_LINK;
-}
-
-static const char *
-ot_bootloader_uboot_get_name (OtBootloader *bootloader)
-{
- return "U-Boot";
-}
-
-static gboolean
-create_config_from_boot_loader_entries (OtBootloaderUboot *self,
- int bootversion,
- GPtrArray *new_lines,
- GCancellable *cancellable,
- GError **error)
-{
- gs_unref_ptrarray GPtrArray *boot_loader_configs = NULL;
- OstreeBootconfigParser *config;
- const char *val;
-
- if (!ot_admin_read_boot_loader_configs (self->sysroot, bootversion, &boot_loader_configs,
- cancellable, error))
- return FALSE;
-
- /* U-Boot doesn't support a menu so just pick the first one since the list is ordered */
- config = boot_loader_configs->pdata[0];
-
- val = ostree_bootconfig_parser_get (config, "linux");
- if (!val)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "No \"linux\" key in bootloader config");
- return FALSE;
- }
- g_ptr_array_add (new_lines, g_strdup_printf ("kernel_image=%s", val));
-
- val = ostree_bootconfig_parser_get (config, "initrd");
- if (val)
- g_ptr_array_add (new_lines, g_strdup_printf ("ramdisk_image=%s", val));
-
- val = ostree_bootconfig_parser_get (config, "options");
- if (val)
- g_ptr_array_add (new_lines, g_strdup_printf ("bootargs=%s", val));
-
- return TRUE;
-}
-
-static gboolean
-ot_bootloader_uboot_write_config (OtBootloader *bootloader,
- int bootversion,
- GCancellable *cancellable,
- GError **error)
-{
- OtBootloaderUboot *self = OT_BOOTLOADER_UBOOT (bootloader);
- gs_unref_object GFile *new_config_path = NULL;
- gs_free char *config_contents = NULL;
- gs_free char *new_config_contents = NULL;
- gs_unref_ptrarray GPtrArray *new_lines = NULL;
-
- /* This should follow the symbolic link to the current bootversion. */
- config_contents = gs_file_load_contents_utf8 (self->config_path, cancellable, error);
- if (!config_contents)
- return FALSE;
-
- new_config_path = ot_gfile_resolve_path_printf (self->sysroot, "boot/loader.%d/uEnv.txt",
- bootversion);
-
- new_lines = g_ptr_array_new_with_free_func (g_free);
-
- if (!create_config_from_boot_loader_entries (self, bootversion, new_lines,
- cancellable, error))
- return FALSE;
-
- new_config_contents = ot_admin_join_lines (new_lines);
-
- if (strcmp (new_config_contents, config_contents) != 0)
- {
- if (!g_file_replace_contents (new_config_path, new_config_contents,
- strlen (new_config_contents),
- NULL, FALSE, G_FILE_CREATE_NONE,
- NULL, cancellable, error))
- return FALSE;
- g_print ("Saved new version of %s\n", gs_file_get_path_cached (self->config_path));
- }
-
- return TRUE;
-}
-
-static void
-ot_bootloader_uboot_finalize (GObject *object)
-{
- OtBootloaderUboot *self = OT_BOOTLOADER_UBOOT (object);
-
- g_clear_object (&self->sysroot);
- g_clear_object (&self->config_path);
-
- G_OBJECT_CLASS (ot_bootloader_uboot_parent_class)->finalize (object);
-}
-
-void
-ot_bootloader_uboot_init (OtBootloaderUboot *self)
-{
-}
-
-static void
-ot_bootloader_uboot_bootloader_iface_init (OtBootloaderInterface *iface)
-{
- iface->query = ot_bootloader_uboot_query;
- iface->get_name = ot_bootloader_uboot_get_name;
- iface->write_config = ot_bootloader_uboot_write_config;
-}
-
-void
-ot_bootloader_uboot_class_init (OtBootloaderUbootClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
-
- object_class->finalize = ot_bootloader_uboot_finalize;
-}
-
-OtBootloaderUboot *
-ot_bootloader_uboot_new (GFile *sysroot)
-{
- OtBootloaderUboot *self = g_object_new (OT_TYPE_BOOTLOADER_UBOOT, NULL);
- self->sysroot = g_object_ref (sysroot);
- self->config_path = g_file_resolve_relative_path (self->sysroot, "boot/uEnv.txt");
- return self;
-}
+++ /dev/null
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
- *
- * Copyright (C) 2013 Collabora Ltd
- *
- * Based on ot-bootloader-syslinux.h by Colin Walters <walters@verbum.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the licence or (at
- * your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
- */
-
-#pragma once
-
-#include "ot-bootloader.h"
-
-G_BEGIN_DECLS
-
-#define OT_TYPE_BOOTLOADER_UBOOT (ot_bootloader_uboot_get_type ())
-#define OT_BOOTLOADER_UBOOT(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), OT_TYPE_BOOTLOADER_UBOOT, OtBootloaderUboot))
-#define OT_IS_BOOTLOADER_UBOOT(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), OT_TYPE_BOOTLOADER_UBOOT))
-
-typedef struct _OtBootloaderUboot OtBootloaderUboot;
-
-GType ot_bootloader_uboot_get_type (void) G_GNUC_CONST;
-
-OtBootloaderUboot * ot_bootloader_uboot_new (GFile *sysroot);
-
-G_END_DECLS
+++ /dev/null
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
- *
- * Copyright (C) 2013 Colin Walters <walters@verbum.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the licence or (at
- * your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-#include "ot-bootloader.h"
-#include "libgsystem.h"
-
-G_DEFINE_INTERFACE (OtBootloader, ot_bootloader, G_TYPE_OBJECT)
-
-static void
-ot_bootloader_default_init (OtBootloaderInterface *iface)
-{
-}
-
-gboolean
-ot_bootloader_query (OtBootloader *self)
-{
- g_return_val_if_fail (OT_IS_BOOTLOADER (self), FALSE);
-
- return OT_BOOTLOADER_GET_IFACE (self)->query (self);
-}
-
-/**
- * ot_bootloader_get_name:
- *
- * Returns: (transfer none): Name of this bootloader
- */
-const char *
-ot_bootloader_get_name (OtBootloader *self)
-{
- g_return_val_if_fail (OT_IS_BOOTLOADER (self), NULL);
-
- return OT_BOOTLOADER_GET_IFACE (self)->get_name (self);
-}
-
-gboolean
-ot_bootloader_write_config (OtBootloader *self,
- int bootversion,
- GCancellable *cancellable,
- GError **error)
-{
- g_return_val_if_fail (OT_IS_BOOTLOADER (self), FALSE);
-
- return OT_BOOTLOADER_GET_IFACE (self)->write_config (self, bootversion,
- cancellable, error);
-}
+++ /dev/null
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
- *
- * Copyright (C) 2013 Colin Walters <walters@verbum.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the licence or (at
- * your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#pragma once
-
-#include <gio/gio.h>
-
-G_BEGIN_DECLS
-
-#define OT_TYPE_BOOTLOADER (ot_bootloader_get_type ())
-#define OT_BOOTLOADER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), OT_TYPE_BOOTLOADER, OtBootloader))
-#define OT_IS_BOOTLOADER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), OT_TYPE_BOOTLOADER))
-#define OT_BOOTLOADER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), OT_TYPE_BOOTLOADER, OtBootloaderInterface))
-
-typedef struct _OtBootloader OtBootloader;
-typedef struct _OtBootloaderInterface OtBootloaderInterface;
-
-struct _OtBootloaderInterface
-{
- GTypeInterface g_iface;
-
- /* virtual functions */
- gboolean (* query) (OtBootloader *self);
- const char * (* get_name) (OtBootloader *self);
- gboolean (* write_config) (OtBootloader *self,
- int bootversion,
- GCancellable *cancellable,
- GError **error);
-};
-
-GType ot_bootloader_get_type (void) G_GNUC_CONST;
-
-gboolean ot_bootloader_query (OtBootloader *self);
-
-const char *ot_bootloader_get_name (OtBootloader *self);
-
-gboolean ot_bootloader_write_config (OtBootloader *self,
- int bootversion,
- GCancellable *cancellable,
- GError **error);
-
-G_END_DECLS
-